<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>errno</title><link>https://errno.jofrey.eu/</link><description>Recent content on errno</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Sat, 05 Sep 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://errno.jofrey.eu/index.xml" rel="self" type="application/rss+xml"/><item><title>A phone input mask that silently rewrote the number I typed</title><link>https://errno.jofrey.eu/posts/jquery-mask-silently-rewrites-phone-number/</link><pubDate>Sat, 05 Sep 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/jquery-mask-silently-rewrites-phone-number/</guid><description>&lt;blockquote&gt;&#10;&lt;p&gt;Numbers in this post are placeholders; the original test used a real number that has been redacted.&lt;/p&gt;&#10;&lt;/blockquote&gt;&#10;&lt;h2 id="what-happened"&gt;What happened&lt;/h2&gt;&#10;&lt;p&gt;A registration form had a mobile number field with a national format mask:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-html" data-lang="html"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;text&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;form-control mask-phone&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;phone&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;maxlength&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;14&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;minlength&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;14&amp;#34;&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Mobile number&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;I filled it with a foreign number in international form. The field did not go red, no message appeared —&#10;the value became:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;input: +421900123456&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;field: 06&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Typing digit by digit was worse. The mask pre-seeds the national trunk prefix, so my leading digits were&#10;consumed as part of it and the rest shifted:&lt;/p&gt;</description></item><item><title>Cloudflare Email Routing rejects mail with 550 5.7.26 "not authenticated"</title><link>https://errno.jofrey.eu/posts/cloudflare-email-routing-550-5-7-26-not-authenticated/</link><pubDate>Sat, 05 Sep 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/cloudflare-email-routing-550-5-7-26-not-authenticated/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;&#10;&lt;p&gt;A freshly created routing rule (&lt;code&gt;contact@example.com&lt;/code&gt; → a Gmail mailbox) looked configured. Sending a test&#10;message straight to the MX from a host with no outbound mail authentication failed at the DATA stage:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;smtplib.SMTPDataError: (550, b&amp;#39;5.7.26 Cannot forward emails that are not authenticated.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Refer to https://developers.cloudflare.com/email-routing/postmaster/ for more information..&amp;#39;)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Note &lt;strong&gt;where&lt;/strong&gt; it failed: &lt;code&gt;MAIL FROM&lt;/code&gt; and &lt;code&gt;RCPT TO&lt;/code&gt; were both accepted, so it is not an unknown-recipient&#10;or configuration problem.&lt;/p&gt;</description></item><item><title>HTTP 522 after pointing a domain at Cloudflare Pages (and the Search Console fallout)</title><link>https://errno.jofrey.eu/posts/cloudflare-pages-custom-domain-522-switch-dns-after-active/</link><pubDate>Sat, 05 Sep 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/cloudflare-pages-custom-domain-522-switch-dns-after-active/</guid><description>&lt;h2 id="what-i-did-and-what-broke"&gt;What I did, and what broke&lt;/h2&gt;&#10;&lt;p&gt;Migrating a static site to Cloudflare Pages, in this order:&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;code&gt;POST /accounts/{id}/pages/projects&lt;/code&gt; — create project&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;wrangler pages deploy public --project-name …&lt;/code&gt; — upload, deployment succeeded&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;POST /accounts/{id}/pages/projects/{p}/domains&lt;/code&gt; — add &lt;code&gt;site.example.com&lt;/code&gt;&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;immediately&lt;/strong&gt; repoint the DNS record to &lt;code&gt;&amp;lt;project&amp;gt;.pages.dev&lt;/code&gt;, proxied&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;Seconds later:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -sSI https://site.example.com/&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/2 522&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;server: cloudflare&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cf-ray: a3664d60bfb3386b-LHR&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The domain was serving Cloudflare&amp;rsquo;s &amp;ldquo;connection timed out&amp;rdquo; error, because the Pages side had not finished&#10;attaching it:&lt;/p&gt;</description></item><item><title>reCAPTCHA v3 rejects your headless Chromium and no fingerprint patch fixes it</title><link>https://errno.jofrey.eu/posts/recaptcha-v3-rejects-headless-chromium-validation-failed/</link><pubDate>Sat, 05 Sep 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/recaptcha-v3-rejects-headless-chromium-validation-failed/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;&#10;&lt;p&gt;An end-to-end check drives a form on a site I am allowed to automate. In a normal browser session the&#10;submission succeeds. From headless Chromium, the token is generated without error — &lt;code&gt;grecaptcha.execute()&lt;/code&gt;&#10;resolves and returns a 2 361-character token — but the backend rejects it:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;success&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;errors&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nt"&gt;&amp;#34;general&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;validation.recaptchav3&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]}}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The important detail: &lt;strong&gt;the failure is not client-side&lt;/strong&gt;. There is no exception, no missing site key, no&#10;network error. The token exists and is syntactically fine. reCAPTCHA v3 is score-based, and the score&#10;arrives at the server too low to pass its threshold.&lt;/p&gt;</description></item><item><title>MCP server dies at startup after the mcp package resolves to 2.0.0</title><link>https://errno.jofrey.eu/posts/mcp-server-crashes-at-startup-after-mcp-2-0-0/</link><pubDate>Fri, 04 Sep 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/mcp-server-crashes-at-startup-after-mcp-2-0-0/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;&#10;&lt;p&gt;Two stdio MCP servers that had worked for weeks stopped appearing in the client. No tools, no error dialog&#10;— the server process simply exits during startup, and the client shows it as failed to connect. Running it&#10;by hand shows why:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-gdscript3" data-lang="gdscript3"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;AttributeError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Server&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;object&lt;/span&gt; &lt;span class="n"&gt;has&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt; &lt;span class="n"&gt;attribute&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;list_tools&amp;#39;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nothing in the project changed. That is the tell.&lt;/p&gt;&#10;&lt;h2 id="cause-an-unpinned-sdk-and-a-fresh-resolution"&gt;Cause: an unpinned SDK and a fresh resolution&lt;/h2&gt;&#10;&lt;p&gt;The server&amp;rsquo;s dependency spec was permissive:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mcp&amp;gt;=0.9.0&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;uv&lt;/code&gt; re-resolves on each run when there is no lock file in play, and the newest release satisfying that&#10;range became &lt;strong&gt;2.0.0&lt;/strong&gt;, which removed the decorator-style &lt;code&gt;Server.list_tools()&lt;/code&gt; API the server was written&#10;against. The code is fine; it is simply talking to a different major version than the one it was built for.&lt;/p&gt;</description></item><item><title>gpsoauth returns BadAuthentication on a 2FA Google account (app passwords do not help)</title><link>https://errno.jofrey.eu/posts/gpsoauth-badauthentication-2fa-master-token/</link><pubDate>Thu, 03 Sep 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/gpsoauth-badauthentication-2fa-master-token/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;&#10;&lt;p&gt;Getting a master token for a library that speaks Google&amp;rsquo;s mobile auth protocol (in my case &lt;code&gt;gkeepapi&lt;/code&gt; for&#10;Google Keep) starts with &lt;code&gt;gpsoauth&lt;/code&gt;. On an account with 2FA enabled it fails:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;gpsoauth&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;gpsoauth&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;perform_master_login&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;me@gmail.com&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;…&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;android_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Error&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BadAuthentication&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;ErrorDetail&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The reflex is to generate an &lt;strong&gt;app password&lt;/strong&gt; and retry. It fails the same way. App passwords work for&#10;IMAP/SMTP, not for this endpoint, so no amount of retrying the password path will produce a token.&lt;/p&gt;</description></item><item><title>Graylog 7 API: POST /api/streams returns 400 "entity cannot be null"</title><link>https://errno.jofrey.eu/posts/graylog-7-create-stream-api-400-entity-cannot-be-null/</link><pubDate>Wed, 26 Aug 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/graylog-7-create-stream-api-400-entity-cannot-be-null/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;&#10;&lt;p&gt;A stream-creation call that worked against Graylog 6 now fails:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -sS -u &amp;#34;$USER:$PASS&amp;#34; -H &amp;#39;X-Requested-By: cli&amp;#39; -H &amp;#39;Content-Type: application/json&amp;#39; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -d &amp;#39;{&amp;#34;title&amp;#34;:&amp;#34;nginx&amp;#34;,&amp;#34;description&amp;#34;:&amp;#34;nginx access logs&amp;#34;,&amp;#34;remove_matches_from_default_stream&amp;#34;:false}&amp;#39; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; https://graylog.example.com/api/streams&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/1.1 400 Bad Request&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{&amp;#34;type&amp;#34;:&amp;#34;ApiError&amp;#34;,&amp;#34;message&amp;#34;:&amp;#34;entity cannot be null&amp;#34;}&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Nothing in the message points at the payload shape, so the natural assumption — a missing required field&#10;such as &lt;code&gt;index_set_id&lt;/code&gt; — sends you down the wrong path.&lt;/p&gt;&#10;&lt;h2 id="cause"&gt;Cause&lt;/h2&gt;&#10;&lt;p&gt;In Graylog 7 the endpoint takes a &lt;code&gt;CreateEntityRequest&lt;/code&gt;: the stream itself moved one level down, under an&#10;&lt;code&gt;entity&lt;/code&gt; key. Send the same fields wrapped:&lt;/p&gt;</description></item><item><title>Synology NAS: scp fails with "subsystem request failed on channel 0"</title><link>https://errno.jofrey.eu/posts/synology-scp-subsystem-request-failed-on-channel-0/</link><pubDate>Sat, 22 Aug 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/synology-scp-subsystem-request-failed-on-channel-0/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;&#10;&lt;p&gt;SSH into the NAS works. Copying a file off it does not:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ssh nasuser@nas.example.lan &amp;#39;echo login ok&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;login ok&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ scp nasuser@nas.example.lan:/volume1/media/clip.mp4 .&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;subsystem request failed on channel 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;scp: Connection closed&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;sftp&lt;/code&gt; fails the same way:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ sftp nasuser@nas.example.lan&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Connection closed.&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;subsystem request failed on channel 0&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="diagnosis"&gt;Diagnosis&lt;/h2&gt;&#10;&lt;p&gt;Modern &lt;code&gt;scp&lt;/code&gt; no longer uses the legacy remote-copy protocol; it speaks &lt;strong&gt;SFTP&lt;/strong&gt;, which requires the server&#10;to offer an &lt;code&gt;sftp&lt;/code&gt; subsystem. On this DSM installation, that subsystem is not exposed, so the channel&#10;request is rejected before any transfer starts. The interactive shell is unaffected, which is exactly why&#10;the failure looks so confusing: authentication, host key and network are all fine.&lt;/p&gt;</description></item><item><title>docker manifest inspect fails with "permission denied" on /etc/docker/certs.d</title><link>https://errno.jofrey.eu/posts/docker-manifest-inspect-permission-denied-certs-d/</link><pubDate>Wed, 12 Aug 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/docker-manifest-inspect-permission-denied-certs-d/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;&#10;&lt;p&gt;A deployment script verifies that the requested tag exists before it touches a running stack. Under the&#10;deploy user it fails:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-zed" data-lang="zed"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;manifest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;com/&lt;/span&gt;&lt;span class="n"&gt;backend&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="err"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;42&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nn"&gt;etc/docker/&lt;/span&gt;&lt;span class="n"&gt;certs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;d/&lt;/span&gt;&lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nn"&gt;com/&lt;/span&gt;&lt;span class="n"&gt;ca&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;crt&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;permission&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;denied&lt;/span&gt;&lt;span class="w"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Under &lt;code&gt;root&lt;/code&gt; on the same node the identical command returns the manifest. Pulling images works for the&#10;deploy user too, which makes the failure look arbitrary.&lt;/p&gt;&#10;&lt;h2 id="why-root-works-and-your-user-does-not"&gt;Why root works and your user does not&lt;/h2&gt;&#10;&lt;p&gt;&lt;code&gt;docker manifest inspect&lt;/code&gt; is one of the CLI commands that talks to the registry &lt;strong&gt;from the client&#10;process&lt;/strong&gt;, not through the daemon. So it needs to read the registry CA itself — and&#10;&lt;code&gt;/etc/docker/certs.d/...&lt;/code&gt; is intentionally readable only by root and the daemon.&lt;/p&gt;</description></item><item><title>Editing a Subversion repository without a working copy: svnmucc</title><link>https://errno.jofrey.eu/posts/svnmucc-commit-without-working-copy/</link><pubDate>Wed, 12 Aug 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/svnmucc-commit-without-working-copy/</guid><description>&lt;h2 id="the-problem-with-a-checkout"&gt;The problem with a checkout&lt;/h2&gt;&#10;&lt;p&gt;Release repositories tend to be large and deeply nested. Changing one deploy script means a checkout of a&#10;tree you do not care about, a build-up of stale working copies on a jump host, and a real risk of&#10;committing something you did not intend because the working copy had other local modifications.&lt;/p&gt;&#10;&lt;p&gt;For scripted or one-off edits, skip the working copy entirely.&lt;/p&gt;&#10;&lt;h2 id="svnmucc-multiple-url-commands-one-commit"&gt;svnmucc: multiple URL commands, one commit&lt;/h2&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;svnmucc &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; put local/stack-deploy-or-update.sh &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; svn://svn.example.com/svn/release/trunk/projects/app/test/docker/stack-deploy-or-update.sh &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; rm svn://svn.example.com/svn/release/trunk/projects/app/test/docker/portainer-compose.yml &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -m &lt;span class="s2"&gt;&amp;#34;APP: unify deploy script, drop portainer compose&amp;#34;&lt;/span&gt; &lt;span class="se"&gt;\&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --username builder --non-interactive --no-auth-cache&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Everything on that command line lands as &lt;strong&gt;one atomic revision&lt;/strong&gt; — which is the property you want when a&#10;change spans several files and half of it applied would leave the environment broken. The available&#10;operations are &lt;code&gt;put&lt;/code&gt;, &lt;code&gt;rm&lt;/code&gt;, &lt;code&gt;mkdir&lt;/code&gt;, &lt;code&gt;cp&lt;/code&gt;, &lt;code&gt;mv&lt;/code&gt; and &lt;code&gt;propset&lt;/code&gt;, all addressed by URL.&lt;/p&gt;</description></item><item><title>WSL2: /mnt/c fails with "Input/output error (os error 5)" after the laptop sleeps</title><link>https://errno.jofrey.eu/posts/wsl2-mnt-input-output-error-os-error-5-after-sleep/</link><pubDate>Wed, 12 Aug 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/wsl2-mnt-input-output-error-os-error-5-after-sleep/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;&#10;&lt;p&gt;The laptop was suspended with a WSL2 session open. After resume, every path under &lt;code&gt;/mnt&lt;/code&gt; is dead:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ ls /mnt/c&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls: reading directory &amp;#39;/mnt/c&amp;#39;: Input/output error&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ cat /mnt/d/some/file&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cat: /mnt/d/some/file: Input/output error&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Python, Node and anything else that touches those paths reports the same thing as &lt;code&gt;os error 5&lt;/code&gt;:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;OSError: [Errno 5] Input/output error: &amp;#39;/mnt/c&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Native Linux filesystems are unaffected. &lt;code&gt;/&lt;/code&gt;, &lt;code&gt;/home&lt;/code&gt;, &lt;code&gt;/mnt/wsl&lt;/code&gt; and &lt;code&gt;/mnt/wslg&lt;/code&gt; behave normally, and&#10;long-running processes that never touch &lt;code&gt;/mnt&lt;/code&gt; keep going.&lt;/p&gt;</description></item><item><title>Teams incoming webhook returns HTTP 200 but no message appears</title><link>https://errno.jofrey.eu/posts/teams-incoming-webhook-returns-200-but-no-message/</link><pubDate>Tue, 11 Aug 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/teams-incoming-webhook-returns-200-but-no-message/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;&#10;&lt;p&gt;A monitoring or automation job posts to a Teams incoming webhook. The client is happy:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;$ curl -sS -i -H &amp;#39;Content-Type: application/json&amp;#39; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -d &amp;#39;{&amp;#34;text&amp;#34;:&amp;#34;certificate renewed&amp;#34;}&amp;#39; \&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#39;https://example.webhook.office.com/webhookb2/…&amp;#39;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;HTTP/1.1 200 OK&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;acme.sh&lt;/code&gt; reports &lt;code&gt;send success&lt;/code&gt;. Nothing arrives in the channel. No error, no bounce, no entry anywhere.&lt;/p&gt;&#10;&lt;h2 id="the-proof-is-in-the-response-headers"&gt;The proof is in the response headers&lt;/h2&gt;&#10;&lt;p&gt;Look past the status line:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;x-nanoproxy: 1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;x-proxyerrorhresult: 0x80070036&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;x-proxyerrormessage: The network is busy.&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That is not a transient condition despite what it says. Microsoft retired Office 365 connectors, and the&#10;endpoints now answer &lt;code&gt;200&lt;/code&gt; at a proxy while discarding the payload. Any client that only checks the status&#10;code will report success forever, which is why this failure survives in cron jobs and alerting scripts for&#10;months.&lt;/p&gt;</description></item><item><title>Reading and writing MediaWiki pages from a script: action=raw and the two-token login</title><link>https://errno.jofrey.eu/posts/mediawiki-api-write-page-reader-mode-redirect/</link><pubDate>Wed, 05 Aug 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/mediawiki-api-write-page-reader-mode-redirect/</guid><description>&lt;h2 id="reading-skip-the-html-ask-for-raw-wikitext"&gt;Reading: skip the HTML, ask for raw wikitext&lt;/h2&gt;&#10;&lt;p&gt;Fetching an article URL with a normal client and parsing the HTML is where most scripts start, and it goes&#10;wrong in a way that is easy to miss: a plain &lt;code&gt;GET&lt;/code&gt; of the page URL can land you on &lt;strong&gt;Recent Changes&lt;/strong&gt;&#10;instead of the article — a redirect that a browser resolves invisibly but that leaves your parser looking&#10;at completely different content and &amp;ldquo;working&amp;rdquo;.&lt;/p&gt;</description></item><item><title>Word tracked changes in a .docx: python-docx cannot do it, raw XML can</title><link>https://errno.jofrey.eu/posts/docx-tracked-changes-without-python-docx/</link><pubDate>Tue, 28 Jul 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/docx-tracked-changes-without-python-docx/</guid><description>&lt;h2 id="the-constraint"&gt;The constraint&lt;/h2&gt;&#10;&lt;p&gt;A release-management document had to come back with &lt;strong&gt;native Word tracked changes&lt;/strong&gt; — the reviewer wanted&#10;to accept or reject each edit in Word, not read a changelog. The obvious tool does not do it:&lt;/p&gt;&#10;&lt;p&gt;python-docx exposes runs, paragraphs and styles, but &lt;strong&gt;no API for revisions&lt;/strong&gt;. There is no&#10;&lt;code&gt;run.insert_tracked()&lt;/code&gt;, and writing the text through python-docx produces a document where your edits are&#10;indistinguishable from the original. If tracked changes are a requirement, you are editing OOXML directly.&lt;/p&gt;</description></item><item><title>When an MCP wrapper hides API fields: set Redmine parent, due date and estimate over REST</title><link>https://errno.jofrey.eu/posts/redmine-mcp-wrapper-missing-fields-use-rest/</link><pubDate>Wed, 17 Jun 2026 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/posts/redmine-mcp-wrapper-missing-fields-use-rest/</guid><description>&lt;h2 id="symptom"&gt;Symptom&lt;/h2&gt;&#10;&lt;p&gt;An agent-facing MCP wrapper for Redmine exposes issue creation and updates, but only a subset of the&#10;fields:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;subject, description, assigned_to_id, status_id, priority_id, done_ratio&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So a task can be created — but it cannot be attached to a parent, given a deadline, or given an estimate.&#10;There is no error to debug; the parameters simply do not exist in the tool schema, which is a worse failure&#10;mode, because the model happily reports success on a partially created issue.&lt;/p&gt;</description></item><item><title>About</title><link>https://errno.jofrey.eu/about/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/about/</guid><description>&lt;p&gt;I am Attila Csontos. I work on infrastructure: Linux, Docker Swarm, monitoring, on-premise deployments&#10;and the long tail of tooling that surrounds them.&lt;/p&gt;&#10;&lt;p&gt;This site exists because of a specific frustration. When a system throws&#10;&lt;code&gt;Input/output error (os error 5)&lt;/code&gt; or &lt;code&gt;subsystem request failed on channel 0&lt;/code&gt;, a search usually returns&#10;three kinds of pages: someone with the same problem and no answer, a generic tutorial that never mentions&#10;the error, or a page that lists five &amp;ldquo;solutions&amp;rdquo; that the author clearly never ran.&lt;/p&gt;</description></item><item><title>Contact</title><link>https://errno.jofrey.eu/contact/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/contact/</guid><description>&lt;p&gt;Email: &lt;span class="eml" data-e="Y29udGFjdEBqb2ZyZXkuZXU="&gt;contact [at] jofrey [dot] eu&lt;/span&gt;&lt;/p&gt;&#10;&lt;p&gt;Useful things to send:&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;A correction.&lt;/strong&gt; If a fix here does not work on your version, send the version and the exact output.&#10;Corrections are published with a dated note.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;A missing detail.&lt;/strong&gt; If a post skips a step that was obvious to me and not to you, that is a bug in the post.&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Privacy or legal requests.&lt;/strong&gt; See &lt;a href="https://errno.jofrey.eu/privacy/"&gt;Privacy&lt;/a&gt; and &lt;a href="https://errno.jofrey.eu/terms/"&gt;Terms&lt;/a&gt;.&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;I answer in English, Slovak and Hungarian. I do not accept guest posts, link exchanges or sponsored&#10;articles — the site would lose the only thing that makes it worth reading.&lt;/p&gt;</description></item><item><title>Privacy policy</title><link>https://errno.jofrey.eu/privacy/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/privacy/</guid><description>&lt;p&gt;&lt;em&gt;Last updated: 5 September 2026&lt;/em&gt;&lt;/p&gt;&#10;&lt;p&gt;This site is a static website. There is no user account, no login, no comment form and no newsletter.&#10;I collect no personal data directly.&lt;/p&gt;&#10;&lt;h2 id="hosting"&gt;Hosting&lt;/h2&gt;&#10;&lt;p&gt;The site is served by &lt;strong&gt;Cloudflare Pages&lt;/strong&gt; (Cloudflare, Inc.). Cloudflare processes technical connection&#10;data — including your IP address, user agent and requested URL — to deliver the pages and to protect the&#10;service against abuse. See Cloudflare&amp;rsquo;s own privacy documentation for details and retention periods.&lt;/p&gt;</description></item><item><title>Terms of use</title><link>https://errno.jofrey.eu/terms/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://errno.jofrey.eu/terms/</guid><description>&lt;p&gt;&lt;em&gt;Last updated: 5 September 2026&lt;/em&gt;&lt;/p&gt;&#10;&lt;h2 id="no-warranty"&gt;No warranty&lt;/h2&gt;&#10;&lt;p&gt;Everything here describes what happened on &lt;strong&gt;my&lt;/strong&gt; systems, with the versions stated in each post.&#10;Commands touch filesystems, containers, network configuration and production services. Read them before&#10;running them, and adapt them to your environment. You run them at your own risk; I accept no liability for&#10;data loss, downtime or any other damage.&lt;/p&gt;&#10;&lt;h2 id="accuracy-and-versions"&gt;Accuracy and versions&lt;/h2&gt;&#10;&lt;p&gt;Software changes. A fix that is correct for Graylog 7.x or Hugo 0.165 may be wrong two releases later.&#10;Each post states the version it was verified against. Where I could not verify a claim, it is marked as&#10;unverified in the text.&lt;/p&gt;</description></item></channel></rss>