Blog
89 posts, newest first. Subscribe with RSS.
Start here
Posts that make sense on their own.
Agents on shared machines: four ways they quietly hurt the host
I run a fleet of coding agents on machines I own. Most are shared: agents, my own work, and a few long-running services on the same box.
A colour convention that looked like a sim-to-real gap
I built a render generator and a 20,000-image benchmark to ask one question.
October 2026
One unquoted attribute skips the whole tag: PathConverter and B64 in pymdown-extensions
Raw HTML such as <img src="a.png" width=100> kept its src as written in pymdown-extensions, a Python library of Markdown extensions: PathConverter did not rewrite it…
Config media type used as artifact type: FilterArtifactType in oras-go
A copy that used opts.FilterArtifactType(regexp.MustCompile("sbom")) skipped a referrer whose artifactType was application/vnd.example.sbom.v1, and "empty" copied it.
A start-tag search over the whole reply: non-stream reasoning in Xinference
A non-stream chat reply that had no <think> before </think> but mentioned one after it either failed with an HTTP 500 or came back with the wrong reasoning_content.
Checking the new chunk first: a repeated end tag in streamed replies in Xinference
Once a streamed reply's reasoning had ended, a later </think> in the answer was read as the end of the reasoning again.
A start tag inserted ahead of a newline: streamed reasoning in Xinference
A streamed reply that starts with a lone newline chunk, with reasoning_content on, put the model's own <think> inside reasoning_content.
A group opener consumed as a repeated star: star groups in wcmatch
In wcmatch, a Python glob and fnmatch library, a star directly before an extended star group, as in a(b), was not read as followed by the group (b).
A key lowered on lookup but stored as is: unique glob results in wcmatch
In wcmatch, a Python glob and fnmatch library, glob.glob and glob.iglob returned a path twice when two patterns found it, IGNORECASE was set and the path had an upper…
A year limit inherited from datetime: range matching for week inputs in soupsieve
In soupsieve, the CSS selector library behind Beautiful Soup, :in-range and :out-of-range raised ValueError for a week input with a week-year of 10000 or more.
A cached count that left out one element: :nth-last-child(an+b of S) in soupsieve
In soupsieve, the CSS selector library behind Beautiful Soup, :nth-last-child(an+b of S) returned the wrong elements when the first sibling it checked did not match S.
A Bessel function that overflows before the result: the VonMises log-density in PyMC
In PyMC, a Python library for probabilistic programming, VonMises.logp returned -inf for a large concentration kappa: from about 92 in float32, from about 710 in float64.
A copy that shared the original's hook lists: with_options in Prefect
In Prefect, a Python workflow orchestration library, with_options made a copy of a task or flow that shared a hook list with the original whenever that list already…
Escapes refused or read in halves: quoted strings in OjG
OjG, a Go library for JSON, refused \/ in a quoted name and read an escaped UTF-16 pair as two U+FFFD. RFC 9535 section 2.3.1.1 allows both.
A not that read to the end of the filter: the ! operator in OjG
In OjG, a Go JSON library with JSONPath, ! in a filter took in every && and || term after it: !@.a && @.b meant !(@.a && @.b). (!@.a) && @.b already worked.
A minus sign read as part of the operator: negative numbers in OjG filters
jp.ParseString in OjG, a Go JSON library with JSONPath, rejected a filter with no space between an operator and a negative number, such as $[?@.a==-1].
Anchors that split at an alternation: match() in OjG
In the Go library OjG, a JSONPath match() pattern with a top-level | was not tested against the whole string: ab|cd also matched abx and xcd, though RFC 9535 section…
Bytes counted instead of characters: length() of a string in OjG
length() of a string in OjG, a Go JSON library with JSONPath, returned the number of bytes, so "жж" had a length of 4.
An escaped emoji decoded as two U+FFFD: JSON strings in OjG
The oj, gen and sen parsers in OjG, a Go library, decoded an emoji written as an escaped UTF-16 pair, \ud83d\ude00, as two U+FFFD.
Equal operands that never satisfied <= or >=: filter comparisons in OjG
In OjG, a Go JSON library with JSONPath, <= and >= in a filter never matched two equal null, boolean, array or object values, or two missing values. == did.
An empty pattern that matched nothing: match() and search() in OjG
An empty pattern, '', made match() and search() select nothing in OjG, a Go library for JSON.
A dot that matched a carriage return: match() and search() in OjG
match(@, '.') and search(@, '.') selected a string that was one carriage return in OjG, a Go JSON library.
A tab, line feed or carriage return refused as blank space: JSONPath queries in OjG
A JSONPath filter written over two lines did not parse in OjG, a Go library for JSON.
Blank space refused before a segment and in a slice: JSONPath parsing in OjG
$ .a and $[1:5 :2] were parse errors in OjG, a Go library for JSON, though RFC 9535 allows blank space before a path segment and between the parts of a slice.
A support lost in a pytree round trip: Levy in NumPyro
NumPyro, a probabilistic programming library on JAX, lets a distribution cross a jit boundary as a pytree. The Levy distribution came out the other side with no support.
A second stored copy of the bounds: the interval supports in NumPyro
Uniform, LogUniform and DiscreteUniform in NumPyro stored their bounds twice: as low and high, and again inside a cached support.
Doubled timestamps cut a recording every 5 seconds: MPEG audio in mediamtx
A 20-second MP3 stream became three recording files in mediamtx, and audio between them was lost.
Removed ranges kept on the Service: loadBalancerSourceRanges in Kamaji
Clients outside a TenantControlPlane's old source ranges stayed blocked after the ranges were removed from it.
An update checked against the old object: the DNS service IP webhook in Kamaji
A TenantControlPlane could be edited to a DNS service IP outside its service CIDRs.
An error that was logged, not returned: the DataStore lookup in Kamaji
Kamaji hosts Kubernetes control planes as pods.
A log line that read the wrong error: the API server certificate check in Kamaji
A one-line mistake in a log call made Kamaji's reconcile panic when apiserver.crt was missing from the API server certificate Secret.
Infinity fetched any URL a client sent it: SSRF fixed in 0.0.78
The Infinity embedding server (infinity-emb on PyPI) downloads images and audio from URLs that clients send it.
Strings and numbers rejected as sources: TypedArray.from in goja
Uint8Array.from("123") threw in goja, a JavaScript engine in Go: TypeError: Value is not an object: 123. Node returns Uint8Array(3) [ 1, 2, 3 ].
A method that never read exec: RegExp.prototype.test in goja
RegExp.prototype.test in goja, a JavaScript engine in Go, never read exec. A plain object with exec threw, and a replaced exec was ignored.
A nil exec was called: generic RegExp replace and split in goja
An empty object as this made RegExp.prototype[Symbol.replace] panic with a nil pointer in goja, a JavaScript engine in Go.
An undefined exec threw: RegExp match, search and global replace in goja
Setting exec to undefined on a regexp made match, search and a global replace throw in goja, a JavaScript engine in Go.
A length nothing checked: Array.from on array-likes in goja
In goja, a JavaScript engine in Go, Array.from({length: 232}) did not return in any practical time. Node throws RangeError: Invalid array length.
Run start reported as run end: LastRunStartedAt in gocron
With WithIntervalFromCompletion(), Job.LastRunStartedAt() returned the time the last run ended. gocron is a job scheduler for Go.
A one-value filter failed: VALUE_IN on list requests in Flyte
A Flyte ListActions request with a VALUE_IN filter and one value failed with an internal error. With two values it returned rows. Flyte orchestrates ML pipelines.
Terminated pods that hold their names: PodSet replacement in AIBrix
A PodSet in AIBrix, a control plane for serving LLMs on Kubernetes, never replaced a pod that ended Failed or Succeeded.
An unset strategy that nothing defaulted: RayClusterFleet in AIBrix
A RayClusterFleet in AIBrix, a control plane for serving LLMs on Kubernetes, never created a RayClusterReplicaSet when its strategy was unset.
An end index counted from zero: content after a leading newline in Xinference
A non-stream chat reply with a newline before the <think> tag came back with a stray > at the start of content.
A parser branch that assumed no start tag: unfinished replies in Xinference
A non-stream chat reply that stopped inside the thinking block, for example at max_tokens, came back with <think> at the front of reasoning_content.
A count zeroed by a nested call: inverse extended globs in wcmatch
!(a)@(b|(c)) raised re.error in wcmatch, a Python library for wildcard and glob matching, although Bash accepts it.
User and guest counts passed twice: USG mobile and handheld in unpoller
A USG exported its user count as mobile and its guest count as handheld in unpoller_device_stations. I fixed it in PR #1114, merged within two hours of opening it.
One label dict for every table: positional factor labels in tox
In tox, a Python tool that runs test environments, a project with two env_base tables using positional factor labels got empty labels for every table but the last.
An allof loop where anyof is the default: CardDAV prop-filter in Radicale
A CardDAV addressbook-query with two conditions in one prop-filter returned only the cards that matched both. RFC 6352 says a prop-filter is anyof unless it says allof.
A group that dropped the existence check: parenthesized paths in OjG
In OjG, a Go JSON library with JSONPath, a bare @.x in a filter tests that x exists, but (@.x) beside &&, || or ! did not.
Go's == where value equality belongs: the in filter in OjG
The in filter in OjG, a Go JSON library with JSONPath, panicked when its left operand was an array or object and the list held a member of the same kind.
A reset that skipped a removed block: kube-apiserver extraArgs in Kamaji
Deleting the whole extraArgs block from a TenantControlPlane in Kamaji, which runs Kubernetes control planes as pods, left its flags on the kube-apiserver container.
An assignment to no name: extract_function in Jedi
Script.extract_function in Jedi, a Python library for editor autocompletion and refactoring, wrote code that does not parse when the extracted lines define no name.
Truncation where jq rounds down: slice start index in gojq
In gojq, a pure Go implementation of jq, a slice with a negative fractional start such as .[-1.5:] returned a different result than jq.
A hold count raised before the path was resolved: acquire in filelock
FileLock.acquire() in filelock, a Python library for file locks, raised FileNotFoundError when the working directory was gone.
A template that quoted without escaping: JSON tag export in ezdxf
export_json_tags() in ezdxf, a Python library for DXF drawing files, wrote JSON that json.loads rejected, or read back as a different string, when a string value held a…
An assignment that erased a flag: map keys-sorted in arrow-schema FFI export
Exporting a Field of DataType::Map(, true) through arrow-schema's C Data Interface dropped the keys-sorted flag, so it came back as Map(, false). I fixed it in PR #11630.
Counter rules keyed with a suffix the parser drops: runtime metrics in AIBrix
The runtime sidecar in AIBrix, a control plane for serving LLMs on Kubernetes, copies engine metrics to aibrix: names.
Your SSRF allowlist forgets the redirect
You added a destination check to the URL fetcher, so it only talks to hosts you trust. Good.
Four early exits dropped the chunk: empty reasoning streams in Xinference
A streamed chat reply with no text at all, from a reasoning model that needs the <think> tag added, reached the client as data: [DONE] and nothing else.
Label names declared in the wrong order: temperature and storage in unpoller
unpoller_device_temperature_celsius and unpoller_device_storage put the tag and the sensor or disk values under the wrong label names, and lost series too.
Label names declared in the wrong order: station counts in unpoller
unpoller_device_stations put the device tag in station_type and the station type in tag, and lost series too.
Three review requests from this week, and what I changed
These are three requests from this week. All three arrived on 2026-10-17: two from reviewers and one from a bot's label.
The cheap gate I run before reading an inference server's code
One shape is worth checking first in a model inference server: the server fetches a URL the client handed it, with no authentication and no check on where the URL points.
An empty case in a Go switch: scrape mode changes on reload in sql_exporter
A reload that switched sql_exporter from one target to jobs returned success and kept the old target.
One condition did two jobs: overlapping collector globs in sql_exporter
The README's own collectors example stopped sql_exporter at startup. I fixed the resolver in PR #1117, merged 2026-10-17, 8 minutes and 4 seconds after I opened it.
The cache stored errors like results: min_interval in sql_exporter
With min_interval set, one failed query in sql_exporter kept returning the same error until the interval ended.
One number broke a string map: JSON secrets in sql_exporter
A database secret from AWS made sql_exporter use the whole JSON text as its connection string.
Request input stored on a shared exporter: job filters in sql_exporter
Two scrapes of sql_exporter could ask for different jobs and receive each other's metrics.
Config stored before the build: a failed reload in sql_exporter
After a failed reload, sql_exporter showed a config it was not running. I fixed it in PR #1120, merged within ten minutes of opening it.
Strategic merge kept both halves of an env entry: a merge fix in OME
An InferenceService could override a runtime's environment variable and still inherit half of the old one.
An environment override kept the source it was meant to replace in OME
OME could replace an environment variable's text and leave its old source attached.
A refactor dropped the webhook and controller: BenchmarkJob restored in OME
On OME's main branch, creating a BenchmarkJob failed at admission. If it had passed, nothing would have reconciled it.
Height read from the width: wrong VP9 height in mediamtx fMP4 recordings
mediamtx wrote the wrong height into every fMP4 recording of a non-square VP9 stream. I fixed it in PR #6359, merged within fifteen minutes of opening it.
Loading model weights can run a stranger's code
Downloading a model and loading it feel like reading data.
A collect() that cannot return an error: a key overflow panic in arrow-csv
An arrow-csv reader panicked when a Dictionary(Int8, Utf8) column had 129 distinct values in one batch.
Two route lists, one missing path: image generations in AIBrix
AIBrix's gateway accepted POST /v1/images/generations, but with no routing strategy set, the route it handed the request to had no match for that path, for every engine…
A hardcoded IPv4 address type: ModelAdapter EndpointSlices in AIBrix
AIBrix built every ModelAdapter EndpointSlice with addressType: IPv4, even when the Pods had IPv6 addresses.
The duplicate guard that never recorded a path
I found a set under // avoid duplicates that nothing wrote to.
CreateUser echoed the request, not the record: a stored-limits fix in AIBrix
Calling POST /CreateUser again for an existing user returned the limits from the request, not the ones in the store.
Two URL lists: the adapter webhook and the runtime sidecar
I found that AIBrix could admit an adapter URL and then reject it when the runtime sidecar tried to load it.
TrimPrefix is not TrimLeft: a false warning on every scrape error in sql_exporter
In single target mode, sql_exporter warned about its own log context on every scrape error. I fixed it with a one-word change (PR #1115, merged 2026-10-16 as 72c7582).
Six things code review caught in my upstream pull requests
Apart from k3s #14810, which is another contributor's, I opened the pull requests below between 2026-10-05 and 2026-10-16, in a number of open-source projects, and most…
An index that trusted the disparity map: the validateDisparity fix in OpenCV
My fix for an out-of-bounds access in OpenCV's cv::validateDisparity was merged into the 4.x branch today as PR #30316.
Two goroutines, one receive: a leak in the k3s tunnel proxy
k3s leaked a goroutine, its 32 KiB buffer and both connections whenever the two copy directions of a tunnel connection failed at about the same time.
Reading git output with -z, and the test that could not run on Windows
oh-my-openagent prints a [FILE CHANGES SUMMARY] block after a task finishes. It lists modified, created and deleted files with their line counts.
Encrypting every record to read one name: a fix in external-dns
external-dns synchronizes Kubernetes Services and Ingresses with DNS providers.
A verify target that rewrote the tree: four review points on a cri-tools script change
make verify-docs and make verify-go-modules in cri-tools rewrote files in your working tree, then failed if git status showed anything dirty.
Two directories for one adapter: a Hugging Face download fix in AIBrix
AIBrix's runtime handed the inference engine a different directory for the same LoRA adapter, depending on whether the adapter had been downloaded before.
One local variable, one reference cycle per error reply in redis-py
On 2026-10-15 redis-py merged a small fix I sent: #4434, "Break the ResponseError reference cycle in asyncio read_response".
One String() call per pod: 320x faster in one kube-router function
I got a small change merged into kube-router (PR #2192). The code change deletes five lines; I also added a test and a benchmark.
A colour convention that looked like a sim-to-real gap
I built a render generator and a 20,000-image benchmark to ask one question.
Agents on shared machines: four ways they quietly hurt the host
I run a fleet of coding agents on machines I own. Most are shared: agents, my own work, and a few long-running services on the same box.
All 54 tags
- go, 32 posts
- testing, 17 posts
- python, 15 posts
- jsonpath, 12 posts
- prometheus, 6 posts
- reasoning, 6 posts
- config, 5 posts
- globs, 4 posts
- caching, 3 posts
- code-review, 3 posts
- concurrency, 3 posts
- json, 3 posts
- streaming, 3 posts
- webhooks, 3 posts
- datetime, 2 posts
- environment-variables, 2 posts
- error-handling, 2 posts
- labels, 2 posts
- logging, 2 posts
- lora, 2 posts
- networking, 2 posts
- open-source, 2 posts
- performance, 2 posts
- recording, 2 posts
- refactoring, 2 posts
- reload, 2 posts
- routing, 2 posts
- rust, 2 posts
- agents, 1 post
- api, 1 post
- audio, 1 post
- benchmarks, 1 post
- build-scripts, 1 post
- carddav, 1 post
- computer-vision, 1 post
- dns, 1 post
- docker, 1 post
- endpointslices, 1 post
- ffi, 1 post
- gateway, 1 post
- git, 1 post
- hugging-face, 1 post
- ipv6, 1 post
- jq, 1 post
- memory, 1 post
- memory-safety, 1 post
- numerics, 1 post
- rfc, 1 post
- rounding, 1 post
- secrets, 1 post
- stereo, 1 post
- strategic-merge, 1 post
- unifi, 1 post
- vp9, 1 post