Skip to content

[BUG] set-field silently writes the WRONG option when --option-id and a positional value are both supplied #110

Description

@ryan-baum

Summary

set-field accepts an invocation that combines both of its documented, mutually exclusive forms — --option-id <id> and a positional value — and resolves it to an option that is neither inert nor the requested one. It exits 0. Nothing on stdout or stderr indicates a problem.

The severity is not the wrong write itself but its shape: the value that landed was a plausible sibling option, so it reads as intentional to a human reviewing the node afterwards. A no-op leaves a visible gap; this leaves a confident, wrong answer.

Observed

On a #task node whose ☑️ STATUS field (7mbhvC0_YEcA) has these options:

Option Id
✅ Completed gUMBCHgDKvj9
❌ Dropped -MG-UldK1Pn2

this argv:

set-field --field-id 7mbhvC0_YEcA --option-id gUMBCHgDKvj9 -- <nodeId> 7mbhvC0_YEcA "✅ Completed"

exited 0, and the field was left holding ❌ Dropped (-MG-UldK1Pn2) — not the requested gUMBCHgDKvj9.

Expected

Either the documented precedence is honoured (--option-id wins), or — better — the ambiguous invocation is rejected with a non-zero exit, since the README defines the two forms as alternatives rather than composable:

supertag set-field <nodeId> <attributeId> "value"
supertag set-field <nodeId> <attributeId> --option-id <optionId>

(README, "MUTATE — Edit Existing Nodes".) The option form takes no third positional, so supplying one alongside --option-id is a caller error that is currently absorbed rather than surfaced.

I'd argue rejection is the right fix rather than a documented precedence: any precedence rule still silently discards half of what the caller asked for, and the failure mode here is a wrong value written to a user's graph.

Minimal repro

# Pick any options-type field and two of its option ids.
supertag set-field --field-id <fieldId> --option-id <optionA> -- <nodeId> <fieldId> "<label of optionA>"
supertag read <nodeId>          # field holds neither reliably; observed: a third option

Provenance — what I verified and what I didn't

Being explicit, because it bears on how you triage this:

  • Verified. The argv above is exact — it is constructed by a wrapper whose source I control, and the resulting state was read back from the graph. The write was recorded as successful by the wrapper because the process exited 0.
  • Not verified. I have not reproduced this by invoking the CLI directly at a shell, and I have not determined why -MG-UldK1Pn2 was chosen. I am deliberately not asserting a mechanism (positional-beats-flag, label fuzzy-matching, index arithmetic) — the binary is compiled and I had no way to inspect the resolution path. The reproducible, actionable fact is that the combined invocation is accepted and does not honour --option-id.

I have since changed my wrapper to never emit a positional value alongside --option-id, which resolves it on my side. Filing because the ambiguous invocation is silently accepted for everyone.

Two smaller things found alongside

1. --field-id is undocumented. The README shows <attributeId> as a positional only, but --field-id <id> is accepted and is in practice the only reliable way to target a field — by name, set-field fails with NODE_NOT_FOUND against a field-scoped URL:

Resource not found: http://127.0.0.1:8262/nodes/<node>/fields/<FieldName>/content

Worth documenting, or making the name path work.

2. Dash-leading ids as flag values — unverified, flagging in case it's the same class. Tana option and node ids can begin with - (❌ Dropped above is -MG-UldK1Pn2). I already hit a confirmed instance of this class with positionals: a node id -P11YGvsvmBb passed as a bare positional produced error: unknown option '-P11YGvsvmBb' from the commander parser, which I work around by placing all positionals after --. I have not tested whether --option-id -MG-UldK1Pn2 (space form) hits the same parser behaviour — I moved to --option-id=-MG-UldK1Pn2 (equals form), which works. If the space form does mis-parse, then ❌ Dropped-style options are unsettable by id without the = spelling, which is worth a README note either way.

Environment

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions