Files
hq/04-ISSUES/244-a-verb-whose-schema-is-empty-cannot-be-called-through-the-console/00-report.md
T
jschoubben 8ade75c550 ADR 0189 collects again; issue 244: a verb with an empty schema cannot be called
The nightly collector is back on the store (mesh-catalog#57). It was out for
a day because while-stopped named the module-local id and the host refuses a
declaration naming a container it does not have, whole; the namespacing was
fixed the same night and the composition was read before anything was sent
this time — plan's distribution.collect shows while-stopped as
distribution.store. novox applied it with no refusal and the registry was
untouched.

The store is 40G at 14:37, the filesystem 56% full; the collector first fires
at 03:30. Deleting a manifest frees no bytes until then, so that is the
number to read against.

244: mesh-controller.plan and .node publish an empty schema and then refuse
with 'needs node', including when node is passed — the console drops what
the schema does not declare. A tool that cannot be called is worse than one
that is absent, because it is listed. Worked around through the login shell,
which is the path the console exists to replace.
2026-10-05 14:38:17 +02:00

3.0 KiB

status, opened, located-in, fixed-by, amended-design
status opened located-in fixed-by amended-design
open 2026-10-05
mesh-tools
mesh-controller

244 — A verb whose published schema is empty cannot be called through the console, and says only that it needs the argument it will not take

What was observed

Through the console, 2026-10-05, composing one machine's declaration before pushing it:

mesh_describe  mesh-controller.plan
  → {"properties": {}, "type": "object"}        ... it takes nothing

mesh_call      mesh-controller.plan  {}
  → plan failed: plan needs "node"              ... it takes something

mesh_call      mesh-controller.plan  {"node": "novox"}
  → plan failed: plan needs "node"              ... and not that

mesh-controller.node describes the same way and behaves the same way. Both are listed in the node's own instructions as the mesh's verbs, so they are the first thing a session reaches for.

The verb is not broken where it runs: the same plan novox --json through the machine's login shell answers in full. What cannot be done is calling it through the console, which the node's instructions say is the only way to the mesh.

Why

Not diagnosed past the symptom, and the symptom is specific enough to place it: the published schema declares no properties, and an argument that is not in the schema does not reach the verb. So the verb reports a missing argument that the console has dropped, every time, whatever is sent. The two halves are each defensible — publish a schema, honour it — and together they make a verb that can only refuse.

Why it matters beyond this instance

A tool that cannot be called is worse than one that is absent, because it is listed. It appears in mesh_overview, it describes itself, and the only thing it will say is that it wants something it will not accept. A reader has no way to tell that from their own mistake, and the obvious next move — pass the argument it names — is the one that does not work.

It also marks what the console does not check. Nothing compares a verb's published schema against the arguments the verb actually requires, so a verb can be published in a shape that makes it uncallable and nothing says so. That is the shape of an unenforced rule: the schema is believed, and it is wrong.

What a fix has to settle

  • Where the schema for a seat's verbs comes from, and why these two publish an empty one while the verbs beside them (status, builds, push) take their arguments and answer.
  • Whether the console should refuse to publish a verb whose schema cannot satisfy it, rather than listing one that can only fail.
  • How it is checked: every verb the console lists is callable with the arguments its own schema describes — a test that calls each with its schema's required set and asserts the answer is not "needs" an argument the schema does not have.

Worked around, for now

Through <node>/node-login-shell.execute, running the controller's own command line on the machine. That is the path the console exists to replace, so it is a workaround and not an answer.