This page is disputed and low-confidence — its sources disagree. A reconciliation is open on the discussion. Read with care.
Summary
The Claude Code changelog is the running, versioned record of fixes, behavioral changes, and new capabilities across releases of Anthropic's terminal coding agent, published at code.claude.com/docs/en/changelog. The page covers releases through v2.1.321 (November 9, 2026), alongside earlier ingestion passes: a day-238 scan (read 2026-10-24) carrying v2.1.309 (2026-10-22) and v2.1.310 (2026-10-23), and a later changelog entry dated October 26, 2026 spanning v2.1.287–v2.1.310 with eight additional fixes. The previous revision of this page listed v2.1.289 (2026-10-03) as its newest entry; later scans extend the record and reframe it as a parity checklist.
A separately ingested set of release notes covers a further release train that concentrates on four areas: making auto mode's server-side safety check explicit rather than silently degrading, tightening permission enforcement so that crafted commands and rule shapes cannot slip past it, expanding the Claude apps gateway's administrative and billing controls, and clearing a long tail of data-integrity, sign-in, plugin and UI defects. Alongside those, MCP tool calls can now run as backgrounded tasks in the terminal, subagents become reopenable via /tasks, and self-hosted runners gain stricter workspace trust and per-repository checkout folders. A notable number of the fixes address writes that could leave ~/.claude.json, settings files or edited files empty or truncated, and several address permission prompts that were either needless (read-only commands under timeout) or absent (a sed command in accept-edits and auto mode).
The v2.1.321 entry adds a newer cluster: correctness of the session-start git snapshot, bounded output in background notifications, honest exit codes when persistence fails, cwd isolation across parallel Bash tool calls, a new default Fable model, and MCP tool-loading races.
Read from the perspective of a competing/parallel agent project, the changelog functions as a pre-graded validation ledger: every entry is a defect someone else already hit, diagnosed, and shipped a fix for — a free signal about which of your own open tickets describe real failure modes and which design decisions they still owe. The newest entry makes this explicit by comparing each fix against the analogous behaviour in yoyo, a separate agent runtime (runtime component ), to surface independent convergence on the same bug class and catalog/lifecycle drift that yoyo will eventually have to track.
yoagent
The page covers several distinct periods or passes of activity, plus triage passes that recast entries as a coverage matrix against the yoyo agent. The v2.1.240–v2.1.245 release window (August 22–25, 2026) contains one substantive feature release — v2.1.243 — plus two reliability patches: per-loop usage accounting in /usage, a curated /model picker, configurable prompt-cache TTLs for the main conversation and subagents, and org-contracted pricing for cost display and telemetry. The day-206 delta scan (2026-09-22) found a later feature cluster around subagent nesting and background execution, MCP failure visibility in headless JSON output, a sandbox network allowlist, a new directory-added hook, a self-diagnosing /doctor command, and refreshed default models (Opus 5, Sonnet 5) plus a workflow-size guideline. The v2.1.289-era entries center on output integrity and runtime hygiene: partial-answer preservation when a turn dies mid-stream, a doomed-retry loop fix, hook trust gating, and abort transcript cleanup.
Key Points
Auto mode no longer falls back to the built-in classifier when telemetry or feature flags are off; calls the server cannot check are asked about or denied. CLAUDE_CODE_AUTO_MODE_SERVER=0 restores the built-in classifier, =1 forces the server-side check behind an LLM gateway. Bedrock, Vertex and Foundry are unchanged.
MCP tool calls that an MCP server runs as a task are backgrounded immediately in the terminal, with the result delivered to Claude on completion. CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND restores waiting inside the tool call; CLAUDE_CODE_DISABLE_MCP_TASKS=1 turns task support off entirely.
New permissions.denyInsteadOfPrompting setting denies a tool call that would block on a permission prompt and lets the turn continue — in terminal sessions, subagents and teammates.
CLAUDE_CODE_DISABLE_FEATURE_FLAGS stops feature-flag fetching without disabling telemetry; every flag then uses its built-in default.
Claude apps gateway gains pooled-budget precedence settings (admin.pooled_conflict_rule, admin.pooled_priority_order), a login_notice operator message, JSON operational logs via CLAUDE_GATEWAY_LOG_FORMAT=json, and per-period /usage spend for developers without a spend limit.
Sign-in fixes cover erroneous 401 loops that spread to other sessions, expired gateway sign-in sending refused telemetry and managed-settings requests logged as invalid_token, and a warning when a claude.ai login hands off to an ant auth login Console-billed session.
Permission enforcement fixes close a sed bypass in accept-edits and auto mode, a crafted environment-prefix bypass, and rule matching that missed commands written with quoted words; a sandbox escape when creating a worktree is fixed.
File and diff integrity: a top-level HEAD file no longer breaks session diffs, /diff no longer opens blank after 64+ file-editing turns, and disk-full saves no longer leave config or edited files empty or cut off.
Self-hosted runners: --trust-workspace false now also blocks hooks from repository settings files and skills; CLAUDE_RUNNER_CHECKOUT_PATH gives each repository its own folder with -2, -3, … suffixes.
Proxy and certificate handling is reworked around CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, HTTPS_PROXY and CLAUDE_CODE_PROXY_RESOLVES_HOSTS.
Terminal UI changes: /model groups older models under "More models", /context trims each list to its 10 largest rows, and secondary gray text has higher contrast.
VSCode prompts over 50,000 characters are no longer silently truncated.
v2.1.321: session-start git status no longer mislabels an unstaged file as staged; a failed git status now reads as unavailable rather than clean.
v2.1.321: background notifications and TaskStop show only the head and tail of output over 1000 characters.
v2.1.321:claude -p now reports lost transcript lines from a full disk and exits 1 instead of silently exiting 0.
v2.1.321: concurrent Bash calls no longer collide on cwd when one call cd-s while others are in flight.
v2.1.321:claude-fable-5-2 becomes the default Fable model — 1M context, $8/$40 per Mtok, $0.20 cache read.
v2.1.321: an MCP server no longer reports connected with zero tools after a reconnect or directory change during tool loading.
Framing note: the page doubles as a parity checklist — earlier passes in particular recast fixed defects as a coverage matrix against a parallel agent project.
Concepts
Auto mode server-side check — the permission decision for auto mode is made by a server-side classifier rather than Claude Code's built-in one. Telemetry/feature-flag availability and LLM gateway placement determine whether the check can run; the CLAUDE_CODE_AUTO_MODE_SERVER variable controls fallback behaviour.
MCP task — a tool call that an MCP server executes as a background task rather than a synchronous call. Claude Code can background it, notify Claude on completion, or (with the disable flags) wait inline or opt out entirely.
permissions.denyInsteadOfPrompting — a setting that converts a blocking permission prompt into an automatic denial so the turn proceeds.
Claude apps gateway — the operator-run proxy in front of Claude apps and Claude Code, with its own admin settings, pooled group budgets, upstream warnings and operational logging.
Pooled group budget — a shared spend pool; when a developer belongs to several groups, admin.pooled_conflict_rule and admin.pooled_priority_order decide which group pays first.
Self-hosted runner — the customer-hosted execution environment for sessions, configured by flags such as --trust-workspace, --use-anthropic-git-proxy, --configure-git and --remove-session-state.
Artifact database — the store behind artifact documents; saves now emit a hidden marker file per saved file so concurrently written rows are detected.
Monitor — the WebSocket watch feature whose rules now apply to every Bash command.
Coverage matrix (yoyo / yoagent) — the triage pass that maps changelog entries against the parallel agent project, recasting fixed defects as items its own backlog may still owe.
Porcelain parsing / leading-space trim — git status --porcelain encodes staged vs unstaged in fixed-width columns; trimming leading whitespace collapses that field boundary and misclassifies entries.
Absence vs. failure — a context section that is omitted when a probe fails vs. one that reports unavailable; agents may misread omission as "not a repository".
unwrap_or(0) — defaulting a failed command to a plausible number (0 staged files) instead of signalling failure.
Head+tail truncation — keeping the beginning and end of oversized output rather than only a prefix, so both setup noise and final errors survive.
Exit-code honesty — a non-zero exit for any state where the run's artifact is incomplete.
Parallel tool-call cwd sharing — concurrent shell invocations inheriting a mutable working directory.
MCP server lifecycle — connected/disconnected/tools-loading states and their races.
Details
v2.1.321 (November 9, 2026)
Fix → yoyo analogue → status
#
Claude Code fix (2.1.321)
yoyo analogue
Assessment
1
Session-start git status no longer shows the first listed file as staged when unstaged
Same leading-space porcelain-trim bug fixed same day (#1169, git_stdout decoder)
Independent convergence — same bug, same week
2
Session-start git status reads unavailable when git status fails (was: clean)
context.rs::get_git_status_context_from omits the whole section on failure; unwrap_or(0) makes a failed diff --cached read as 0 staged
yoyo weaker: absence may be read as "not a repo"
3
Background notifications and TaskStop show only head+tail of output over 1000 chars
bash_output_cap (Day 254)
Behaviour already aligned
4
claude -p errored to exit 1 on lost transcript lines from a full disk (was: silent exit 0)
Not yet verified
Open follow-up on session save / auto-save exit codes
5
Bash commands no longer run in the wrong folder when several are sent at once and an earlier one cd-ed
MCP server no longer shows connected with no tools after reconnect/dir change while tools load
Issue family #1134
Same lifecycle class
Session-start git status (items 1–2)
The session snapshot is the model's first impression of the repo, so misreporting it propagates into everything downstream. Two distinct failure modes:
Parsing — the porcelain format's leading column is significant; trimming it flips staged/unstaged for at least the first entry.
Error handling — collapsing "the probe failed" into "nothing to report" produces a confidently wrong picture. Claude Code now distinguishes unavailable from clean; yoyo's omission-of-section plus unwrap_or(0) can manufacture a clean-looking state from a failed command.
The convergence in (1) between two unrelated codebases in the same 24 hours is the notable signal: fixed-width CLI parsing is a recurring trap.
Output truncation (item 3)
Notifications for background commands and TaskStop results now elide the middle of outputs longer than 1000 characters, preserving the head (setup, paths) and tail (errors, summaries). yoyo already does this via bash_output_cap; no change required.
Exit codes on persistence failure (item 4)
A full disk during transcript write previously produced exit 0 from claude -p — a silent data-loss success. It now surfaces the error and exits 1. The open action for yoyo is to audit session save and auto-save paths for the same "swallow the write error, return success" pattern.
Parallel Bash cwd (item 5)
Sending several Bash tool calls concurrently while one of them changes directory could leave later commands executing in the wrong folder. The fix implies per-call working-directory isolation rather than a shared mutable cwd.
Model catalog (item 6)
claude-fable-5-2 is the new default Fable model with a 1M-token context window and pricing of $8/Mtok input, $40/Mtok output, and $0.20/Mtok cache read. yoyo's known-model list contains only claude-fable-5, so this is a drifting-catalog item — a preset for yoagent would be the trigger to update it.
MCP lifecycle (item 7)
An MCP server could advertise connected while exposing no tools after a reconnect or a working-directory change that occurred during tool loading. This belongs to the same class as yoyo's #1134: connection state and tool inventory need to be published atomically, or the intermediate state must be labelled as loading rather than ready.
Open follow-ups
Verify yoyo's exit code when session save / auto-save fails (item 4).
Reconsider yoyo's unwrap_or(0) and section-omission behaviour on git probe failures (item 2).
Add claude-fable-5-2 to the known-model catalog when a yoagent preset exists (item 6).
Earlier release windows
v2.1.240–v2.1.245 (August 22–25, 2026) — one substantive feature release (v2.1.243) plus two reliability patches: per-loop usage accounting in /usage, a curated /model picker, configurable prompt-cache TTLs for the main conversation and subagents, and org-contracted pricing for cost display and telemetry.
Day-206 delta scan (2026-09-22) — a later feature cluster around subagent nesting and background execution, MCP failure visibility in headless JSON output, a sandbox network allowlist, a new directory-added hook, a self-diagnosing /doctor command, and refreshed default models (Opus 5, Sonnet 5) plus a workflow-size guideline.
v2.1.289 era — output integrity and runtime hygiene: partial-answer preservation when a turn dies mid-stream, a doomed-retry loop fix, hook trust gating, and abort transcript cleanup.
Auto mode and feature flags
Auto mode no longer falls back to the built-in classifier when telemetry or feature flags are disabled, including behind LLM gateways: calls the server cannot check are asked about or denied. Setting CLAUDE_CODE_AUTO_MODE_SERVER=0 restores the built-in classifier; Bedrock, Vertex and Foundry behaviour is unchanged. Behind an LLM gateway, CLAUDE_CODE_AUTO_MODE_SERVER=1 enables the server-side check even when CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS is set — and where managed settings set the latter, they must also set the 1, since that value was previously ignored when the gateway URL was configured only in managed settings and server-managed settings could not be fetched.
Related fixes: a project's settings files or a plugin can no longer switch the server-side check back on once it has been switched off outside the project. Auto mode no longer refuses actions without explanation when permission rules or autoMode settings are very large — it explains, and unless autoMode deny rules are set, asks in the terminal. It also no longer wrongly refuses when a client sends a model change and an auto-mode request back to back. claude -p used to exit 0 in auto mode when its actions were refused for lack of a safety check; text and JSON output now exit 1. /status no longer shows "Auto mode server: Enabled" when server-side review is not reaching the session, for example through a gateway that drops it.
CLAUDE_CODE_DISABLE_FEATURE_FLAGS stops feature-flag fetching without disabling telemetry; every flag then uses its built-in default.
MCP tasks
When an MCP server runs a tool call as a task, Claude Code backgrounds it immediately in the terminal and tells Claude the result when it finishes. CLAUDE_CODE_DISABLE_MCP_TASK_BACKGROUND makes Claude Code wait for the task inside the tool call instead. MCP tasks now also work in the terminal without feature-flag fetching, covering Bedrock, Vertex, Foundry, LLM gateways and DISABLE_TELEMETRY; CLAUDE_CODE_DISABLE_MCP_TASKS=1 turns them off.
MCP fixes: older-handshake MCP servers that failed to connect or returned empty results because Claude Code declared an extension it only uses with newer servers; and a long-running MCP tool call on a claude.ai connector that sometimes never reported its result after --resume. In v2.1.321, an MCP server could also report connected with zero tools after a reconnect or directory change during tool loading; connection state and tool inventory now need to be published atomically, or the intermediate state labelled as loading rather than ready.
Permissions and safety
permissions.denyInsteadOfPrompting denies a tool call that would wait on a permission prompt and continues the turn, in terminal sessions, subagents and teammates.
Slash commands typed after a leading space, tab or newline were sent to Claude as plain text instead of running; that is fixed.
Bash deny and ask rules no longer miss commands written with quoted words. A sed command that skipped the permission check in accept-edits and auto mode is fixed, as is a Bash permission bypass in which a crafted environment prefix hid part of a command.
Read-only commands wrapped in a plain timeout DURATION (e.g. timeout 30 rg foo) no longer trigger needless permission prompts.
deny/ask rules, hook matchers and disallowedTools entries written with a claude.ai connector's terminal name (mcp__claude_ai_Slack) were ignored in Claude Desktop; effective once Desktop ships this version.
A sandbox escape when creating a worktree is fixed.
A session's exact Bash or PowerShell ask rule is now refused, not asked about, when a broader deny rule covers the command. The Bash tool asks for permission before running which with flags outside a lookup/display set.
--add-dir directories register plugin marketplaces only once that directory's own trust dialog has been accepted.
CLAUDE_CODE_PROXY_RESOLVES_HOSTS can no longer be set from settings files where the host manages the network; set it in the process environment.
With the Bash sandbox on, skills in .claude/skills folders below the starting folder load only if Claude Code is started there or you /cd there.
On macOS and Windows, when a refused path outside the working directories differs only by letter case from a path inside them, the refusal message now names that spelling.
Claude apps gateway
/usage now shows spend for today, this week and this month for developers behind a gateway who have no spend limit (requires the gateway on this version or later). New settings: admin.pooled_conflict_rule and admin.pooled_priority_order pick which pooled group budget pays first for a developer in several groups; login_notice shows an operator-defined message on the gateway's browser verification page and on Claude Code's sign-in screen. CLAUDE_GATEWAY_LOG_FORMAT=json turns operational log lines into JSON with severity, time and message, for collectors that read the level from a field.
New boot warning when another policy's availableModels also allows a custom model id that one policy lists by name, plus start-up warnings for policies with no desktopHome that rely on coworkTabEnabled: false or chatSessionRetentionDays, ahead of Claude Desktop's November 10 change.
Warnings about a failed upstream call now name the upstream, not only its provider. The spend limit error reads "spend limit reached · resets Dec 1", followed by admin.blocked_message if set. Startup warnings were added for upstreams mixing AWS GovCloud with others and for base URL variables in the gateway's environment, and a start-up log warning fires when managed settings name an Amazon Bedrock guardrail in a header (which the gateway does not forward) while no bedrock upstream sets a guardrail. Claude Desktop no longer offers a web search tool that always failed when every upstream is Amazon Bedrock.
Sign-in
When a claude.ai login ends and Claude Code continues on the sign-in from ant auth login (billing to your Claude Console organization), a warning appears; startup also names the billed Console organization in that case. Two defects are fixed: a request that kept failing with 401 and refreshed login on every retry, causing 401s in other sessions; and terminals whose gateway sign-in had expired sending telemetry and managed-settings requests the gateway refused and logged as invalid_token.
Also fixed: a ~0.5s hang after Enter on the /login success screen — the dialog now dismisses immediately and the post-login refresh runs in the background.
Diffs and file integrity
A session's diff failed to load on claude.ai and mobile apps when the working folder contained a file or folder named HEAD; /diff likewise showed "Diff unavailable" when a git repo had a top-level HEAD.
The /diff pane opened blank in sessions where 64 or more turns edited files.
~/.claude.json, settings and edited files could end up empty or cut off when the disk filled during a save in a read-only folder or to a bind-mounted file; one session now saves at a time. On Windows, Claude Code waits longer for a file another program has open, so a kill mid-save is less likely to leave ~/.claude.json empty.
Write ended the turn as a refusal when it could not read the file to overwrite.
Background Bash commands that finished almost instantly lost output while being reported as completed; the Bash tool's diff of changed files also missed a file written just before the command ended.
CLAUDE_CODE_RESUME_INTERRUPTED_TURN re-ran a turn interrupted in plan mode when the session resumed in another permission mode.
/rewind failed with "No files were restored" when restoring to a checkpoint from before /branch, and restored or deleted a file through a directory symlink.
Edits to a settings file were ignored when made within a few seconds of Claude Code writing that file. A config file left at the legacy name could silently hide setup; Claude Code now reports on stderr when a home holds two config files and says which is in use.
The artifact database gives an improved error when an update targets a document that does not exist, and when the service pauses repeated refused writes. Saves of rows others may have written now give each file a hidden marker file; existing files without one (including earlier versions' exports) are left alone and reported.
In v2.1.321, claude -p previously exited 0 when transcript lines were lost to a full disk; it now reports the failure and exits 1.
Git status and parallel Bash (v2.1.321)
The session-start git snapshot had two bugs. A porcelain parsing bug — trimming the leading space — mislabelled an unstaged file as staged; yoyo shipped the identical fix the same day, independently. Separately, a failed git status was reported as clean rather than unavailable, a difference yoyo handles differently and arguably worse: its context.rs::get_git_status_context_from omits the whole section on failure, and unwrap_or(0) makes a failed diff --cached read as 0 staged files. Since the session snapshot is the model's first impression of the repo, misreporting it propagates downstream. The convergence on the fixed-width parsing trap is the notable signal.
Sending several Bash tool calls concurrently while one of them changed directory could leave later commands executing in the wrong folder. The fix implies per-call working-directory isolation rather than a shared mutable cwd; yoyo shares the same design-level exposure.
UI and terminal experience
/tasks gained an "Earlier in this session" row listing finished subagents, so one can be reopened and messaged after it leaves the list or after a restart. /loop confirmations in cloud sessions now note that a timer stops with its container, offering a loop that survives. Self-paced /loop ends when a turn finishes without rescheduling instead of scheduling a fallback wakeup; CLAUDE_CODE_LOOP_KEEPALIVE=1 restores the old behaviour.
/model groups older models under a "More models" row instead of listing them after current ones. /context keeps its terminal table short — each list keeps its 10 largest rows, and MCP tools that load on demand share one row per server until called — and no longer sends its full visual grid to Claude on every later turn (Claude reads only the table). /usage in cloud sessions links to Settings → Usage on claude.ai when plan limits cannot be shown. Contrast of faint gray secondary text (hints, details in /stats, /model, /sandbox, rejected-action messages) is improved.
Other terminal fixes: Claude Code listed every project file at start on Linux for NFS, SMB, Lustre and similar network file systems; monitor's WebSocket watch failed with "could not resolve" behind a proxy when CLAUDE_CODE_PROXY_RESOLVES_HOSTS was involved; Ctrl+G did not open the external editor while typing an "Other" answer in screen reader mode; and help links in /status and the auto mode billing notice opened only part of the address when they wrapped.
Plugins, hooks and subagents
/rename used to report plain success when the new name could not be saved to the session transcript; it now warns that the new name may not last. ${CLAUDE_PLUGIN_ROOT} is substituted in a plugin-provided subagentStatusLine command, so it can reference the plugin's own scripts. claude plugin update and /plugin "Update now" now install dependencies added by the new plugin version.
Subagents are no longer told after compaction to expect a completion notice for background agents they neither started nor took over. A background agent's later report was sometimes lost silently; the notification now says it was refused and how to ask for it. After safeguards stop a subagent, Claude is told to retry with a narrower prompt or tell the user, instead of doing the work itself. PostToolUse hooks run, with up to 10 seconds to finish, on tool calls that finish after a new message interrupts the turn. Subagent hand-back reports no longer show an internal marker and provenance note when expanded outside verbose mode.
Proxy, certificates and networking
Certificate errors behind a TLS-inspecting proxy persisted when CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC was set; with it set, Claude Code now makes a TLS handshake with the configured API host after a certificate failure — through your http:// proxy if one is set — and sends no API request. Separately, the automatic certificate repair no longer runs when ALL_PROXY is the only proxy variable set; set HTTPS_PROXY to the proxy's http:// URL instead.
Idle background sessions started through a shell-exported LLM gateway were leaving the gateway after an update; that is fixed.
Self-hosted runners and remote control
--trust-workspace false now also stops hooks in the repository's settings files and skills from running. A runner started with --use-anthropic-git-proxy or --configure-git no longer registers before a failed startup check makes it exit; it exits first. CLAUDE_RUNNER_CHECKOUT_PATH now gives each repository in a session its own folder, with -2, -3, … appended to a name already taken in the session. The end-of-session upload of a session's debug log was removed; a failed session's log stays on the runner host unless --remove-session-state is set. The stalled-setup warning on self-hosted environments links to your organization's default or an environment with a live runner, and names it.
claude remote-control no longer exits silently with status 0 when a first-run question gets no answer (scripts, services, batch jobs, Ctrl+C) — it now says why and exits 1. A piped y with no trailing newline at that first-run question now counts as a yes.
claude purge and old-session clean-up retry a folder that could not be fully deleted and report it as an error if it remains.
Cloud sessions and Monitor
Session-scoped allow rules are dropped at a move to a new worker when their deny and ask rules cannot all be kept, so you may be asked again. Scheduled tasks no longer silently drop a connector named memory: runs keep it, mounted under that name plus a short suffix. "Send now" on a waiting message no longer ends running background agents; they keep running.
Monitor's WebSocket watch follows a rule on every Bash command — a deny refuses it, and under an ask rule an allow on Monitor, bypass mode or auto mode no longer skips the prompt.
Tools, SDK and editor integrations
/claude-api latency-optimize finds where Claude API code makes people wait and tries faster settings against your eval. The managed-agents-onboard templates for /claude-api were updated to match the Claude Console — the Performance tuner was removed, two templates renamed, and web search and fetch turned off in five whose prompts do not use them.
claude -p --resume with a prompt no longer loses a deferred tool call when its MCP server is missing: the run exits 1, keeps the call and refuses later input. Text dropped from informational messages sent to SDK clients is fixed, and Agent SDK hosts now get the run's own error instead of a generic exit-code error when the disk was full. A mistyped model name (e.g. opus-5-5) now suggests the intended model instead of telling you to update Claude Code. NotebookEdit no longer changes the wrong cell when the notebook changed while a permission prompt was open. Claude-drafted feedback, surveys and /feedback no longer appear after the server has refused.
Background notifications for long-running commands now show head+tail output over 1000 characters, matching yoyo's bash_output_cap; notifications and TaskStop results preserve setup and final errors rather than eliding the tail.