fix(server): a stored boolean settledOverride no longer stops startup#28314
Problem
A stored thread projection row with a boolean settledOverride (true or false) stops the desktop app and server from starting (T3 Code could not start (code=1)). Startup recovery decodes the row with the thread schema, which only allows "settled" | "active" | null, and the resulting SchemaError aborts the startup phase. Rolling back does not help, because older builds use the same schema. Only the projection row is wrong: no current writer produces the boolean, and the event tables do not contain it.
Reproduced on main (15fe283272) with a fresh isolated server. I ran a real Claude thread, killed the server with SIGKILL so its provider session stayed ready (which puts the thread in the startup recovery set), and set the row's settledOverride to true. The restart exited with code 1: ProjectionStoreReadError → SchemaError: Expected "settled" | "active" | null | undefined at ["settledOverride"]. false fails the same way. When the bad thread is not in the recovery set, the server starts, but sending to that thread fails.
Change
Migration 077 (RepairBooleanSettledOverride) rewrites a stored boolean settledOverride in orchestration_v2_projection_threads: true becomes "settled" (the reporter's manual workaround) and false becomes null. It skips rows whose payload is not valid JSON and leaves every other row untouched. Repairing the stored data, rather than decoding leniently, means the startup decode and the SQL readers that use json_extract on settledOverride (shell index, settled pagination, search, auto-settle) all see the same value. The contracts schema stays strict.
Scope and approval
Fixes pingdotgg/t3code#28279
Verification
077_RepairBooleanSettledOverride.test.tsruns migrations through 76, then storestrue,false,"settled","active",nulland an absentsettledOverride, then runs 077. It asserts thattruebecomes"settled",falsebecomes JSONnull, the other four rows stay byte-identical, and the repaired row decodes withOrchestrationV2AppThreadJson. It fails on the test-only commit 938b709724 (rows unchanged:"type": "true"/"false") and passes at head.Migrations.test.ts,reconcileV2PreviewMigration.test.tsandservicePreflight.test.tspass.vp run check:changedpasses (format, lint, knip, typecheck, tests).- Runtime transcript: identical copies of the same synthetic database (the thread above,
settledOverride: true, sessionready), each started witht3 serve:
| Before (15fe283272) | After (71e4bbc545) |
|---|---|
server runtime startup failedServerRuntimeStartupError: Server runtime startup failed before command readiness.SchemaError: Expected "settled" | "active" | null | undefinedserver exits | V2 orchestration recovery completedmigrations recorded: 77, stored settledOverride now "settled"t3 thread show reads the thread (completed claudeAgent/claude-haiku-5-5) |
- The
falsevariant also exits with code 1 on main. - Not checked: the macOS desktop app itself. The failure and the fix sit in the shared server startup path, which I ran on Linux.
Model: Claude Opus 5.5 (lead, tests, implementation, review B) and GPT-6.1 Sol (review A), via T3 Code.
🤖 Generated with Claude Code
Checks
Added 2 commits
Approvability
Verdict: Approved at 71e4bbc
Macroscope's review found this PR approvable — This migration repairs invalid boolean thread-settlement values that prevent server startup, leaving valid values and other fields unchanged. The narrowly scoped repair is supported by reported migration tests and a successful before/after startup reproduction.
You can add or adjust custom eligibility rules. Learn more.
Thread transfer impact
✅ Thread transfer remains within every enforced ceiling.
| Provider | Metric | Main baseline | This PR | Impact | PR ceiling | |
|---|---|---|---|---|---|---|
| Codex | Total thread wire | 5.0 KiB | 5.0 KiB | 0 B (0.0%) | 6.8 KiB | ✅ |
| Codex | Thread snapshot wire | 3.8 KiB | 3.8 KiB | 0 B (0.0%) | 4.9 KiB | ✅ |
| Codex | Live turn WebSocket wire | 1.2 KiB | 1.2 KiB | 0 B (0.0%) | 2.0 KiB | ✅ |
| Codex | Live turn WebSocket decoded | 21.6 KiB | 21.6 KiB | 0 B (0.0%) | 24.4 KiB | ✅ |
| Codex | Live turn messages | 2 | 2 | 0 (0.0%) | 8 | ✅ |
| Claude | Total thread wire | 5.0 KiB | 5.0 KiB | +29 B (+0.6%) | 6.8 KiB | ✅ |
| Claude | Thread snapshot wire | 3.8 KiB | 3.8 KiB | 0 B (0.0%) | 4.9 KiB | ✅ |
| Claude | Live turn WebSocket wire | 1.2 KiB | 1.3 KiB | +29 B (+2.3%) | 2.0 KiB | ✅ |
| Claude | Live turn WebSocket decoded | 21.9 KiB | 21.9 KiB | +41 B (+0.2%) | 24.4 KiB | ✅ |
| Claude | Live turn messages | 1 | 2 | +1 (+100.0%) | 8 | ✅ |
Baseline: 5fe18d7 · PR result: 71e4bbc · Source CI: success
Scenario and decoded snapshot size
10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.
- Codex decoded thread snapshot: 108.5 KiB
- Claude decoded thread snapshot: 108.8 KiB
Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.
No actionable comments were generated in the recent review.
External image Recent review info
-
External image Run configuration
- Source mode: Auto
- Repository: pingdotgg/t3code
- Branch: fix/issue-28279
- File: .coderabbit.config.ts
- Commit: 71e4bbc
- Layers: Repository TS config
- Review profile: CHILL
- Plan: Team
- Run ID:
ddbb7298-9713-4170-bc2b-c6c23509e980
External image Commits
Reviewing files that changed from the base of the PR and between 5fe18d79ac835e0f193ad61325e5b7d69a317bcf and 71e4bbc545db5c1836e5a9d3ae5f90b0ef85fdfd.
External image Files selected for processing: 4
apps/server/src/persistence/Migrations.tsapps/server/src/persistence/Migrations/077_RepairBooleanSettledOverride.test.tsapps/server/src/persistence/Migrations/077_RepairBooleanSettledOverride.tsapps/server/src/persistence/reconcileV2PreviewMigration.test.ts
Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.
Walkthrough
Migration 77 repairs boolean
settledOverridevalues in valid thread projection JSON. The migration is added to the ordered registry, and tests cover the value conversions and migration sequence.Changes: Thread projection repair
Layer / File(s) Summary Implement and register migration 77
apps/server/src/persistence/Migrations/077_RepairBooleanSettledOverride.ts,apps/server/src/persistence/Migrations.ts,apps/server/src/persistence/Migrations/077_RepairBooleanSettledOverride.test.ts,apps/server/src/persistence/reconcileV2PreviewMigration.test.tsMigration 77 changes boolean trueto"settled"andfalsetonullin valid projection JSON. It is added to the ordered migration registry. Tests check other values, timestamp retention, thread decoding, and migration sequence expectations.Estimated code review effort: 2 (Simple) | ~10 minutes
Change: Bug fix · Severity of issue fixed: Medium
Suggested labels:
bugfix,size:SSuggested reviewers:
t3dotgg
Merge Risk: External image Minimal · up to 71e4b
The migration repairs boolean overrides before thread state is loaded. No merge-blocking risk remains identified.
Pre-merge checks: Passed 4
Check name Status Explanation Title check Passed The title clearly and concisely describes the primary fix: preventing a stored boolean settledOverride from blocking startup. Description check Passed The description includes complete Problem, Change, Scope and approval, and Verification sections. It explains the failure, the migration behavior, linked issue, focused tests, runtime results, and the… Linked Issues check Passed Issue [ #28279] requires startup recovery to handle thread projections with booleansettledOverride. Migration 077 is registered and rewrites valid boolean values in `orchestration_v2_projection_thre…Out of Scope Changes check Passed The changes stay within [ #28279]. They add the required repair migration, register migration 077, and add migration and migration-integration test coverage. No unrelated behavior or product area is ch…Full details: Description check
Explanation
The description includes complete Problem, Change, Scope and approval, and Verification sections. It explains the failure, the migration behavior, linked issue, focused tests, runtime results, and the untested macOS desktop app.
Full details: Linked Issues check
Explanation
Issue [
#28279] requires startup recovery to handle thread projections with booleansettledOverride. Migration 077 is registered and rewrites valid boolean values inorchestration_v2_projection_threads:truebecomes"settled"andfalsebecomes JSONnull. The migration test verifies both repairs, preservessettledAt, preserves non-boolean and absent values, and decodes the repaired thread withOrchestrationV2AppThreadJson.
Full details: Out of Scope Changes check
Explanation
The changes stay within [
#28279]. They add the required repair migration, register migration 077, and add migration and migration-integration test coverage. No unrelated behavior or product area is changed.
Finishing Touches
Generate docstrings
- Commit to this branch
- Create a new PR
Generate unit tests (beta)
- Commit to this branch
- Create a new PR
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
[gpt-6.1-sol][Codex] on behalf of shivam.
Stopping our issue-watch work now that you own this. These results cover main and our unpublished fix, not this PR's head 71e4bbc545db5c1836e5a9d3ae5f90b0ef85fdfd.
On physical shiv, macOS 27.0.1 arm64, source-built T3 Code 0.1.6 / Electron 44.10.0, I reproduced the desktop code=1 failure on main 15fe2832727893cbdd2214383f9f971474849695. The isolated synthetic release-launch fixture had JSON settledOverride: true and a pending message-capable runtime request so the thread entered startup recovery. The backend failed in ProjectionStore.getRuntimeRecoveryProjection with the reported settledOverride schema error. Healthy and "settled" controls opened normally. No real provider turns or live user state were used.
Before, macOS desktop on main:
https://github.com/user-attachments/assets/1c1c898e-51f7-40b6-bc29-0c3b2519d8ac
Our unpublished commit 04ddd4c426abe8df27fd9c59e4f2d6fb8b950815 used a projection-only migration with the same true → "settled", false → null mapping. On the same Mac and corrupted fixture, startup recorded migration 77, SQL changed the boolean to the canonical string, both runtime-recovery spans succeeded, and the desktop opened the seeded thread and rendered its message. The recording below is from that unpublished commit, not your build.
After, macOS desktop on our unpublished repair:
https://github.com/user-attachments/assets/f1c486cd-4193-4c4c-a1f0-26f25e232a01
On corex, the migration regression failed on main with the exact decoder error. With our repair, the focused migration/preview-upgrade/timestamp tests passed, 3 files / 7 tests. vp run check:changed also passed, including 4 test files / 15 tests. Coverage included booleans, both canonical strings, null, absent field, numeric 1 remaining untouched, and preservation of the rest of each payload. A fresh independent Codex review found no issues.
Unverified: your PR, the original writer and reporter database, packaged releases, other desktop platforms, and malformed values introduced after the one-time migration. The false case passed the migration/recovery test but was not separately launched in the Mac app. Two evidence workers hit a Codex API 400 after the successful true-case capture; I recovered and inspected the SQL, successful spans, app screenshot and recording frames over SSH. No branch was pushed and no competing PR was opened.