Skip to content

docs(roadmap): add #455 — missing_credentials JSON hint appended as prose to error field; structured hint stays null#3068

Open
Yeachan-Heo wants to merge 1 commit into
mainfrom
docs/roadmap-455-missing-credentials-hint-prose-vs-structured
Open

docs(roadmap): add #455 — missing_credentials JSON hint appended as prose to error field; structured hint stays null#3068
Yeachan-Heo wants to merge 1 commit into
mainfrom
docs/roadmap-455-missing-credentials-hint-prose-vs-structured

Conversation

@Yeachan-Heo
Copy link
Copy Markdown
Contributor

ROADMAP pinpoint #455 — structured hint field is dead; hint duplicated into error prose

Dogfooded for the 2026-05-24 07:00 Clawhip pinpoint nudge (message 1508001633416777778).

Repro (clean isolated env, ANTHROPIC_* unset, OPENAI_API_KEY set)

{
  "error": "missing Anthropic credentials; export ANTHROPIC_AUTH_TOKEN or ANTHROPIC_API_KEY before calling the Anthropic API — hint: I see OPENAI_API_KEY is set — if you meant to use the OpenAI-compat provider, prefix your model name with `openai/` (e.g. `--model openai/gpt-4.1-mini`) so prefix routing selects the OpenAI-compatible provider, and set `OPENAI_BASE_URL` if you are pointing at OpenRouter/Ollama/a local server.",
  "hint": null,
  "kind": "missing_credentials",
  "type": "error"
}

hint is always null. The actual hint payload is appended as a literal — hint: … prose suffix into the error field.

Root cause

rust/crates/api/src/error.rs:243-275 (Display for ApiError::MissingCredentials):

if let Some(hint) = hint {
    write!(f, " — hint: {hint}")?;
}

The unit test at error.rs:572-599 (missing_credentials_with_hint_appends_the_hint_after_base_message) even asserts:

let hint_marker = " — hint: I see OPENAI_API_KEY is set — …";
assert!(rendered.ends_with(hint_marker));

So the prose suffix is intentional — but the JSON serializer reads Display for the error field, while the structured hint field gets wired to a different (null) source. End result: hint:null in JSON despite missing_credentials_with_hint("…", "…", "I see OPENAI_API_KEY is set") carrying a real hint.

Why distinct from existing items

Item Tracks Surface
#322 Stderr-prefix breaking JSON parse Transport
#340 /session help type vs kind mismatch Vocabulary
#447 All JSON error envelopes on stderr Transport
#450 prompt missing_credentials on stderr Transport
#455 Hint duplicated into error prose; structured hint always null Internal envelope shape

Even when transport and vocabulary are correct, the hint field is structurally dead.

Why it matters

Automation should branch on code/hint/kind without scraping prose. Today, detecting "Anthropic missing but OpenAI key present → switch to --model openai/..." requires regexing the error string for — hint: I see OPENAI_API_KEY instead of reading a typed hint:{adjacent_provider:"openai", suggested_model_prefix:"openai/", suggested_base_url_env:"OPENAI_BASE_URL"}. The regex is brittle; any future hint wording change silently breaks consumers.

Required fix shape (full detail in ROADMAP entry)

(a) Keep Display rendering for text mode (humans need the prose hint), but stop using Display as the JSON error field source. (b) Serialize a base error line + structured hint object such as {kind:"adjacent_provider_detected", provider, suggested_model_prefix, suggested_env_vars[], suggested_base_url_env}. (c) Regression coverage proving JSON envelope has both base error and non-null structured hint when constructed via missing_credentials_with_hint, and the prose — hint: … does NOT appear in the JSON error field. (d) Parity test for every adjacent-provider hint path.

Acceptance check (one-liner)

claw -p 'hi' --output-format json 2>&1 | jq -e '.hint != null and (.error | test(" — hint: ") | not)' should pass when an adjacent provider env var is set.


[repo owner's gaebal-gajae (clawdbot) 🦞]

…rose to error field; structured hint stays null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants