Troubleshooting
Start from the symptom and find the next command to run. Symptoms are grouped roughly in the order you are likely to hit them: startup and auth first, then request failures, sessions, TUI rendering, and performance.
Startup failures
Section titled “Startup failures”Run chord --version in a terminal first to check that the command is available and the program starts. Prebuilt binaries do not need Go; only source builds require checking the Go version and source entry point.
- Command not found or blocked by the OS: check the install path. For downloaded macOS binaries, see Quickstart.
- Missing configuration: run
chordin an interactive terminal and follow the setup wizard. - Invalid configuration: run
chord doctor configand correct the reported YAML or field issues. - Still unable to start: keep the terminal error output, then use the log collection guidance at the end of this page.
The wizard only runs when config.yaml is missing; it does not overwrite an existing malformed file. Without a controlling terminal it returns an initialization error, so complete configuration interactively first.
401 / 403 / auth failures
Section titled “401 / 403 / auth failures”Check:
- Whether provider names in
auth.yamlmatchconfig.yaml - Whether the API key is valid
- Whether OAuth providers have
preset: codex
You can run:
chord doctor modelsTo narrow the check to a known model or model pool:
chord doctor models --model openai/gpt-5.5@highchord doctor models --pool thinking429 / quota exhausted
Section titled “429 / quota exhausted”Common causes:
- the key has reached its quota
- provider rate limiting
- concurrency or high-frequency requests triggering rate limits
Recommendations:
- switch to another key
- reduce concurrency or retries
- check for accidental looped calls
To diagnose which keys or models are hitting rate limits or errors:
- Press
Ctrl+Ein the TUI to open the error panel, which shows all retry errors including 429s with the provider, model, and maskedkey=...label. - Check the error panel to see the pattern: if one specific key is repeatedly hitting 429, that key is rate-limited; if multiple keys on the same provider fail with 503, the provider itself may be degraded.
UI note:
- the right-side RATE LIMIT panel shows the last Codex rate-limit snapshot (e.g.
5h: 42% 2h30m). When a reset timestamp is reached, the countdown may disappear briefly while Chord refreshes usage; depending on provider semantics (rolling windows), usage may drop gradually rather than jumping straight to 0%. - Codex OAuth runtime state is also reloaded from
auth.state.jsonwhen another Chord process updates that file, so quota snapshots, reset timers, account metadata, and account status changes should appear without restarting the current session. - if the RATE LIMIT panel looks stale, enable debug logs with
log_level: debugand checkchord.logfor lines likeresponses codex ws: rate_limits event ...(received) orresponses codex ws: rate_limits event ignored ...(unrecognized / parse failure).
TUI started, but requests fail
Section titled “TUI started, but requests fail”Check:
- whether the current provider / model exists
- whether the network can reach the API
- whether proxy configuration is effective
For example:
curl -I https://api.anthropic.comcurl -I https://api.openai.com/v1OpenAI-compatible 400s and timeouts
Section titled “OpenAI-compatible 400s and timeouts”Set trust_http_400: true for endpoints that follow official API error semantics: Chord then treats HTTP 400 as a terminal request error. The Retry-After header always applies as the key cooldown hint, ahead of any configured retry pacing; retry_after_max_s bounds the longest honored wait (default 60 seconds for third-party gateways, 86400 for preset: codex). For aggregating or proxy gateways that may wrap upstream failures as HTTP 400, set trust_http_400: false or omit the field so unknown 400s can use the normal retry and fallback path.
If requests remain in connecting and then retry, test the endpoint directly, check proxy settings, and inspect the error panel. Chord applies a connection timeout so one unavailable key or gateway does not wait indefinitely.
DeepSeek / OpenAI-compatible thinking-mode 400s
Section titled “DeepSeek / OpenAI-compatible thinking-mode 400s”If you use a chat-completions provider such as DeepSeek and see errors like:
The reasoning_content in the thinking mode must be passed back to the API.Invalid assistant message: content or tool_calls must be set
this usually means the provider requires thinking/reasoning content from the previous tool round to be included again in the follow-up request, with a strict assistant message shape. If the same error keeps repeating, keep the corresponding session dump / trace for diagnosis.
Enable compat.reasoning_continuity.mode: openai_visible on the affected model
or provider. This option replays assistant reasoning_content and lets Chord
map portable visible reasoning from other wire families into
reasoning_content; add any provider-specific thinking flags through
compat.request_overrides.body.
For a third-party OpenAI-compatible gateway, Chord keeps using the configured
endpoint. It never redirects a request to DeepSeek’s official /beta endpoint
or assumes that the gateway implements Chat Prefix Completion. When a reasoning
response is truncated before visible text, Chord makes one bounded,
request-only replay attempt with the accumulated reasoning_content on that
same endpoint, if openai_visible is enabled and the model is unchanged. If
the gateway rejects that message shape, Chord removes the temporary replay and
continues with the ordinary recovery prompt. This is best effort; for gateways
that do not consume reasoning replay, raise the model’s output limit or split
the task into smaller requests.
For GLM Preserved Thinking, that body override must include
thinking.type: enabled and thinking.clear_thinking: false, plus
reasoning_continuity.reasoning_replay: all so Chord keeps completed-turn
reasoning in the replayed history. DeepSeek Chat and Messages routes replay the
complete reasoning_content history automatically, because DeepSeek returns a
400 when a request carries tools without it. Which model IDs Chord treats as
DeepSeek is listed in DeepSeek thinking and history replay;
a third-party route whose model ID matches but serves another backend opts out
with reasoning_continuity.contract: none, and a route whose name Chord does
not recognize opts in with reasoning_continuity.contract: deepseek. In both cases, replayed
reasoning_content must remain complete, unchanged, and in order.
Anthropic also binds each thinking block to the conversation prefix that
produced it, so a history rewrite (context compaction, session restore) can
make the API reject an otherwise intact block with Invalid \signature` in
`thinking` block. The block is bound to a different conversation.` Chord
recognizes that rejection and retries once with the thinking blocks dropped, so
the turn normally continues without manual intervention; the retry keeps the
text and completed tool facts. If the error keeps repeating, export a
diagnostics bundle and include the session ID in your report.
Codex WebSocket 400 “No tool call found for function call output”
Section titled “Codex WebSocket 400 “No tool call found for function call output””Chord normally recovers from this WebSocket conversation-state mismatch automatically by retrying with the full local conversation. If the error repeats, export a diagnostics bundle and include the session ID in your report.
Cache R percentage is much lower than expected
Section titled “Cache R percentage is much lower than expected”Symptom: the info panel shows a cache-read percentage around 50% (or any value far from the actual hit rate) while the request body has barely changed between turns, so the hit rate should be close to 100%.
What to check:
- The percentage is cache-read tokens divided by the full input side
(
uncached + cache-read + cache-write). It only counts the input side, so a large output does not dilute it. - Chord assumes protocol semantics for usage fields: for
messagesproviders,input_tokensis the uncached input and the cache buckets are reported separately; forchat-completions/responsesproviders,input_tokensalready includes the cached portion. - A compatible gateway may report usage with the other protocol’s semantics
while still exposing a
messagesendpoint: most commonlyinput_tokensis the full input including cache hits, andcache_read_input_tokensis only the hit subset. Chord then counts the cache reads twice, which roughly halves the displayed percentage. - To confirm, inspect a session LLM dump and compare its raw usage fields with
the gateway’s usage documentation or a token-counting response for the same
request. If
input_tokensis documented or verified as the full input whilecache_read_input_tokensis only a subset, setcompat.usage.input_includes_cache_read: trueon that provider (see Configuration). The inequality between these two fields alone is not enough to identify their semantics.
Existing usage records are append-only and are not recalculated after a config change; only new requests use the corrected semantics.
MCP never becomes ready
Section titled “MCP never becomes ready”Check first:
- whether the MCP URL is reachable
- whether the config name is correct
- whether local mode is simply still initializing MCP asynchronously
Note: a brief gray pending state right after startup does not necessarily indicate an error.
LSP / MCP rows turn gray after the session is idle
Section titled “LSP / MCP rows turn gray after the session is idle”If the right-side environment panel shows LSP or MCP rows in gray after the agent has been idle for a while, that does not necessarily mean the integration failed.
Chord can unload idle LSP and MCP runtime resources to reduce background cost. In that state:
- the row is shown in a dim gray idle state instead of an error color;
- this means the resource was intentionally unloaded while the session was idle;
- on the next real request / busy cycle, Chord restores the runtime dependency before rebuilding the request surface.
Treat it as a problem only when the row stays red, keeps showing a real connection/configuration error, or the next request fails to restore it.
No diagnostics after writing files
Section titled “No diagnostics after writing files”If you configured LSP but do not see diagnostics after writing files:
- check whether the corresponding language server is installed locally
- check whether the
lspconfig format is correct - confirm the target file type matches
file_types - check whether
diagnostics.enabled: falseturned off post-tool diagnostics - if the tool result carries
LSP diagnostics unavailable for this edit (<server>[: <detail>]); do not treat this edit as verified., Chord could not obtain diagnostics: the server named in the parentheses did not start, is still starting, or exited and is being restarted, or no server published anything within the wait window (cold starts wait longer; this case readslanguage server: no diagnostics within …). The parenthesized detail or the log has the cause. A start failure or exit appears at most once per server per session, a wait timeout at most once per session, and a server that is still starting is named on every edit until it is up.
When a file notification fails, Chord reports diagnostics unavailable and skips the wait instead of presenting old diagnostics as verification. A confirmed transport disconnect removes the affected server instance and its orphaned diagnostics; the next file write restarts it. Cancellation or a rejected protocol request alone does not mark the server disconnected.
For Go, No packages found for open file may be a consequence of package loading failure. Check the LSP log before changing module paths. If it reports too many open files and lsp.gopls.options.gopls.fileWatcher is set, remove it so gopls uses its default off, then restart the affected session. On macOS, watching a large workspace with fsnotify can exhaust file descriptors, and poll also walks every workspace directory. File editing can still succeed while LSP diagnostics are unavailable.
For Python specifically:
- Small files use
diagnostics.python.semantic_backend(usuallylsp.pyright). Make surediagnostics.python.semantic_backend.servermatches the server key underlsp. - Large Python files use Ruff quick diagnostics when
ruffis onPATH. - If a large Python file reports diagnostics skipped because Ruff is unavailable, install Ruff or set
diagnostics.python.large_file.run_semantic_when_quick_unavailable: trueto force Pyright on large files too. - Ruff quick diagnostics do not update the LSP sidebar; they appear only in
edit,apply_patch, orwritetool results and clearly note that full Python semantic diagnostics were skipped.
Recommended Python skeleton:
lsp: pyright: command: pyright-langserver args: ["--stdio"] file_types: [".py", ".pyi"]
diagnostics: python: quick_backend: type: command command: ruffFor the full recommended config, see Configuration: Post-tool diagnostics.
Session resume issues
Section titled “Session resume issues”If --continue or --resume does not appear to work as expected:
- confirm the current directory belongs to the same project as the original session
- try explicitly using
--resume <session-id> - check whether restore is only slow rather than actually lost
Chord automatically repairs incomplete turns caused by an interrupted process before resuming. If restored model/provider state or conversation order looks wrong, export a diagnostics bundle from a current build and include the session ID.
For a tool whose result was never saved, the repaired card shows one of two markers:
- Not started: the tool had not begun executing, so no side effect could have happened. Re-check the preconditions and retry if appropriate.
- Result unknown: the tool had already started, so its side effects may be partially or fully applied. Verify the current file or remote state before retrying.
Chord writes the tool-call message to disk before running the tool, so an interruption cannot leave side effects that Chord does not know were intended. If the session directory becomes unwritable (for example, the disk is full), Chord pauses tool execution to avoid unrecoverable repeated side effects, shows a status card with the cause, and resumes tools automatically once writing succeeds again.
A delegated SubAgent appears stuck or an escalate card keeps running
Section titled “A delegated SubAgent appears stuck or an escalate card keeps running”Two failure modes can make a delegated SubAgent look stuck; Chord recovers both automatically:
If MODEL or Pool is empty after resuming and focusing a SubAgent, Chord first uses model refs stored in the task, recovery snapshot, and usage ledger. When a record has no model data, it resolves the latest Agent configuration, so task or meta files do not need manual editing.
On restore, the durable task_id is the stable identity of delegated work. Agent IDs such as explorer-4 and explorer-6 are successive runtime instances of that task. Historical instance transcripts are merged by task, while the sidebar and focus router expose only the task’s canonical latest instance. Do not treat an older agent_id as a separate task or copy/delete instance files to alter restore behavior.
If the TUI becomes unresponsive after switching to a large SubAgent transcript or pressing Enter to continue from a parked SubAgent, Chord confines the switch to a bounded transcript window and keeps loading the rest in the background. Agents share a workspace skill catalog, but MainAgent and each SubAgent apply their own latest permissions and keep invoked state separate.
Process stderr writes directly to the rotating log file, so a runtime fatal writes its complete stack and exits instead of appearing as a permanent freeze where every key, including raw-mode Ctrl+C, stops working. If the TUI is stuck in this state, terminate it from another terminal and run reset in the original terminal before exporting diagnostics.
- When a parked SubAgent resumes, queued input wakes it; if the worker stays
runningwithout creating a turn, Chord retries the wake once. - If the worker still cannot start, or its provider/model retries end in a terminal error, Chord marks the task failed, records a
risk_alert, and wakes the owner/MainAgent to retry, reassign, or report the blocker. It does not fabricate a successfulcompleteresult.
An escalate request is a local coordination event, not a long-running network operation. If a completed card still looks pending after resume, Chord repairs it when the adjacent messages have the same tool_call_id; unmatched orphan results are discarded.
If a resumed session is still stuck:
- restart with
--resume <session-id>using the current Chord version; - use the stable
task_id, not the previous runtimeagent_id, when retrying or targeting the delegated task; - do not manually edit
agents/*.jsonl,subagents/tasks.json, or mailbox files; - with
log_level: debug, inspectchord.logforstartup watchdog retrying wake,SubAgent failed, orremoved orphan tool messages.
The normal post-response watchdog may ask a live worker to call complete or escalate. A worker that cannot recover is instead closed as failed and routed back to its owner; failure is never treated as successful completion.
TUI cards show strange colors or broken layout when viewing logs / dumps / shell output
Section titled “TUI cards show strange colors or broken layout when viewing logs / dumps / shell output”If a tool card, local shell result, question dialog, or confirmation summary shows unexpected colors, background leaks, or broken wrapping while viewing diagnostic dumps or raw command output:
- retry the same
read,shell,web_fetch, or local shell action - if you still see corruption, save the original file/output and a screenshot together
Chord sanitizes assistant/thinking streaming replies, tool results, local shell output, status/error cards, and tool-request previews such as the apply_patch patch text before rendering them as terminal-safe plain text. Control characters and ANSI escapes such as \x1b[1;1H (a cursor-position command) render as literals instead of corrupting the card layout or its background. A raw carriage return embedded in a patch preview is treated the same way: CRLF still displays as a normal line break, while a standalone CR shows as the literal \r, so the preview cannot reflow mid-line and truncate or miscolor the card background or its left edge. If the same content consistently breaks layout, attach the original text and a screenshot so the rendering case can be reproduced.
Dark block at a card’s right edge or text shifted after an emoji
Section titled “Dark block at a card’s right edge or text shifted after an emoji”If a dark one-column block shows up at the right edge of a card, or text after an emoji sits slightly to the left of where it belongs, your terminal and Chord disagree about how many columns that emoji occupies. There is no authority for emoji cell widths: the same emoji sequence paints anywhere from one to six columns across popular terminals, and a keycap emoji such as 1️⃣ measures two columns while many terminals draw it in one.
Chord measures text by the Unicode-specified widths and compensates in its renderer: any card row that contains a wide glyph is repainted through an erase-to-end-of-line sequence, so the card background always reaches the true end of the line even when the terminal advanced the glyph by fewer columns.
Some residue is known and not solvable at the application level:
- text after a mis-measured emoji can sit shifted within its line;
- on terminals that paint an emoji wider than Chord measured, a column of the row can hold stale content until the next redraw of that row;
- on terminals that fill erased regions with the default background instead of the active one, erased tails render in the default background.
All of these are display-only: session content, scrollback text, and copies are unaffected. To check how closely your terminal follows the width specification, run ucs-detect. When reporting such an artifact, attach a screenshot plus your terminal’s name and version.
Output-triggered TUI render panic / process killed
Section titled “Output-triggered TUI render panic / process killed”If the outer launcher only shows:
Error: program was killed: program experienced a panicand the session must be resumed with --resume, first inspect the end of ~/.local/state/chord/logs/chord.log for the Go panic stack. main.jsonl usually does not contain this panic text because the failure happened in the TUI render path, not as a persisted conversation message.
If the stack contains these frames, treat it as a TUI markdown/ANSI rendering issue first instead of blaming the model or the last tool result directly:
github.com/charmbracelet/x/ansi.(*Parser).Advancecharm.land/lipgloss/v2.(*WrapWriter).Writecharm.land/glamour/v2/ansi.(*HeadingElement).Finishgithub.com/keakon/chord/internal/tui.renderMarkdownContentWhen checking dumps, note:
- If the last shell/tool result before the crash was already written to
main.jsonl, that tool output was usually not lost. - If Chord was waiting on an LLM SSE stream at the time of the crash, the corresponding
dumps/llm/*.jsonmay contain onlyrequest_body, partialsse_chunks, andreading SSE stream: context canceled. That means the LLM response was dumped only up to the interruption, with no complete final text. context canceledis usually a consequence of process shutdown, not necessarily the root cause.
Attach the panic stack, diagnostics bundle, terminal name/version, and the content being rendered to the issue report.
Screen corruption after switching tabs or refocusing the terminal
Section titled “Screen corruption after switching tabs or refocusing the terminal”If the TUI occasionally shows stale rows, horizontal line artifacts, or partially broken tool cards right after switching tabs or returning focus to the terminal window:
- if the screen is already corrupted, lightly resizing the terminal or switching away and back again can force a full redraw
- if it still reproduces, capture a diagnostics bundle and a screenshot together
If you see corruption right after focus restore while the UI is streaming output, capture a diagnostics bundle plus a screenshot so maintainers can compare Chord’s rendered frame with the terminal’s visible output.
Note: fragments like ;250m pyright during a corruption episode are usually not LSP text but the tail of a truncated ANSI/OSC control sequence.
Repeated separator lines / stale border artifacts
Section titled “Repeated separator lines / stale border artifacts”If the main symptom is repeated horizontal lines, duplicated input/status separators, stale card borders, or old sidebar borders:
- Take a screenshot before forcing a redraw. Include the full terminal window, especially the input area, status bar, and right sidebar.
- Export a diagnostics bundle (
Ctrl+G) immediately, before resizing the terminal: the bundle captures the frame Chord most recently rendered, so it lets maintainers tell a Chord-drawn duplicate from a stale terminal artifact. - Attach both to your report, plus your terminal emulator name and version.
Two quick local observations also help narrow it down:
- If the extra line disappears when the terminal is made one or two columns narrower, mention that; it points at right-edge wrap behavior.
- If the artifact appears right after image preview, paste image, or diagnostics export, mention that too.
Bottom transcript rows are unreachable in long sessions
Section titled “Bottom transcript rows are unreachable in long sessions”If the last transcript rows appear clipped, the final card seems to touch the input separator, or scrolling to the bottom still leaves part of the latest conversation hidden:
- pay special attention to whether the issue starts after long-running background jobs or durable status updates in a long session
- if it still reproduces, capture a screenshot and logs so the transcript state can be compared with the rendered bottom rows
A file-edit tool warns that the file changed since it was observed
Section titled “A file-edit tool warns that the file changed since it was observed”This warning means the file changed after the agent last read it. Chord validates edits against the current contents; write and delete may also create a backup before continuing.
Common causes:
- the file was modified by another process (editor/formatter) between
readandedit/apply_patch; - another agent or Chord process changed the file;
- the file changed during a formatter, generator, or build step.
Re-run read before retrying. When Chord manages to create a backup, the tool result names its path under the current session directory together with the source file it snapshots, and the model and the user see the same text. A backup is best effort: when it fails the edit still proceeds, nothing claims a backup exists, and only the local log records why. See Edit tools for edit and apply_patch matching behavior.
apply_patch reports hunk not found
Section titled “apply_patch reports hunk not found”apply_patch matches hunks line-by-line: exact context passes first, then a separate punctuation/whitespace-tolerant step that is applied only when it lands in exactly one place; a tolerant match hitting several positions is rejected with the ambiguous lines named rather than silently taking the first one. Repeated blocks still need enough nearby context to make the intended location clear.
If you see this:
- re-run
readon the file and rebuild the patch from the latest content; - re-copy the target block from the latest
readoutput and make sure context/removal lines match the current indentation; if the hunk came from old numbered output, remove any copied line-number prefix first; - when the same block repeats in the file, add nearby unchanged lines to the
@@hunk, use an@@ headeranchor, or pin a tail edit with*** End of File, so the intended occurrence is unambiguous; - split a broad patch into smaller envelopes or smaller hunks;
- do not run external
apply_patchthroughshell; use Chord’s nativeapply_patchtool so permissions, stale tracking, diffs, LSP, and rollback stay connected.
Performance issues
Section titled “Performance issues”If scrolling, streaming output, or large message rendering feels noticeably slow:
- reduce the current session context size (
/compact, or a new session for unrelated work) - compare behavior in different terminals
See Performance for how rendering and streaming are optimized and how to capture a CPU profile for a bug report.
Compaction not triggering / triggering too often
Section titled “Compaction not triggering / triggering too often”Symptom: context usage is high but compaction never runs; or the opposite: frequent compaction disrupts your workflow.
What to check:
- Verify
context.compaction.thresholdis set and greater than 0 (0 disables automatic compaction). - Check the
Contextpercentage in the TUI footer or info panel. It is based on the usable input budget, not the total context window, so it may be lower than expected (see Context management: Compaction). - If
context.compaction.reservedis set, compaction triggers at a lower absolute token count because the reserve is subtracted before applyingthreshold; if compaction is too frequent, check whether reserved is too large. /compact --notemporarily disables automatic compaction for the current session. Restart the session or run/compactto re-enable.- If your gateway returns missing or zero usage, enable
log_level: debugand look forestimated_input_tokensandeffective_input_tokensin automatic-compaction logs.
Note: loop mode changes neither automatic compaction nor request-level context reduction; both stay enabled.
Reduction trimming important content
Section titled “Reduction trimming important content”Symptom: the model seems to “forget” earlier tool output, but the session file on disk still contains it.
What to check:
- This is normal behavior for context reduction: stale tool output is trimmed from each LLM request prompt, but never modifies session files on disk.
- If you frequently need to revisit earlier read/search results, raise
read_like_age_turnsandread_like_output_bytes. - If build/test logs remain important context, raise
shell_success_bytes. - For more conservative trimming behavior, raise all
*_age_turnsand*_bytesvalues.
See Context management: Reduction.
Requests rejected: “context length” / “input too large”
Section titled “Requests rejected: “context length” / “input too large””Symptom: the provider returns an error like “context length exceeded” or “input too large”.
What to check:
- Verify that
limit.inputandlimit.contextare correctly configured for your model. If the provider publishes a separate input cap, you must also configurelimit.input. - Check if
context.compaction.thresholdis too high, causing automatic compaction to fire too late. - Increase
context.compaction.reservedto trigger compaction earlier, avoiding rejected requests. - If this happens frequently, use
/compactto manually compact immediately, or lowerthreshold. - With
log_level: debug, search the logs foroversizeto confirm whether oversize recovery (compact then retry) was triggered. If automatic compaction is disabled, Chord stops and reports that all attempted candidate models exceeded the current context instead of retrying indefinitely.
A background job’s process is still running but job_list does not show it
Section titled “A background job’s process is still running but job_list does not show it”Symptom: ps shows a process started by a job command, but job_list reports no active jobs.
What to check:
- The job may have finished.
job_listlists only running and stopping jobs by default; passinclude_finished: trueto see retained finished ones, or read the job’s completion card. - The process may have left the job’s process group. A job owns the process group its command starts, so a child that stays in that group keeps the job active; a process that calls
setsidorsetpgid(a daemonizing tool, or a wrapper that detaches) is outside the job and no longer subject to its deadline,job_kill, or session cleanup. Stop it directly. - Plain
command &andnohup command &stay in the group, so they do not escape on their own; only an explicit detach from the process group does. Chord does not scan the process tree for escaped processes. - The job may have stopped without being able to signal the group. Once its command has exited, Chord signals the group only while a member it recorded at that moment is still in that group; a member that left the group on purpose no longer counts. A stop without that evidence is reported as an unconfirmed teardown and the processes it left behind keep running. Look for
no member witnessorno recorded member is still in the groupin the log, and stop those processes directly.
When to check logs
Section titled “When to check logs”Check logs first when you encounter:
- provider request failures where the terminal only shows a summarized error
- context compaction not triggering / context limit issues
- MCP / LSP initialization errors
- hook execution results that differ from expectations
- incomplete headless integration events
Default logs directory: ${XDG_STATE_HOME:-~/.local/state}/chord/logs/. The current log file is chord.log; rotated files are chord.log.1 and chord.log.2.
Override with --logs-dir <path> or CHORD_LOGS_DIR=<path>. To reproduce and collect logs quickly:
chord --logs-dir ./chord-logsLarge OAuth account pools start slowly
Section titled “Large OAuth account pools start slowly”When auth.yaml contains hundreds or thousands of OpenAI / ChatGPT OAuth accounts, Chord loads credential metadata in the background. Missing metadata alone should not block startup.
- Personal Plus/Pro accounts may carry only
user_idand nochatgpt_account_id. They can still be used for ordinary requests, but Chord omitsChatGPT-Account-IDand skips account-id-dependent Codex usage / rate-limit polling for them. account_user_id mismatchoraccount_id mismatchlogs mean metadata explicitly configured inauth.yamlconflicts with what the token itself exposes. Fix or remove that credential.
When manually converting Codex/sub2api exports, keep any available email, account_id, and account_user_id. Use chord doctor models for deliberate account diagnostics.