{"record":{"id":"df25e7588f668c3c","repo":"Hmbown/CodeWhale","slug":"rotate-fixture","errorCode":null,"errorMessage":"rotate fixture","messagePattern":"rotate fixture","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/client.rs","lineNumber":8303,"sourceCode":"        };\n\n        crate::external_credentials::reset_side_effect_trap();\n        let client = CodewhaleClient::new(&config).expect(\"Codex client\");\n        assert_eq!(client.api_key, token_a);\n        assert_eq!(client.codex_account_id.as_deref(), Some(\"account-a\"));\n        assert_eq!(\n            crate::external_credentials::side_effect_trap_counts(),\n            (1, 1),\n            \"bearer and account id must come from one secure open/read\"\n        );\n\n        // An owner rotation after construction cannot splice account B into\n        // the already-resolved bearer snapshot.\n        std::fs::write(\n            &path,\n            serde_json::to_string(&serde_json::json!({\"tokens\": {\"access_token\": crate::test_support::future_test_jwt(\"b\"), \"account_id\": \"account-b\"}})).expect(\"serialize rotated fixture\"),\n        )\n        .expect(\"rotate fixture\");\n        assert_eq!(client.api_key, token_a);\n        assert_eq!(client.codex_account_id.as_deref(), Some(\"account-a\"));\n    }\n\n    fn client_with_config_secret_sentinels() -> CodewhaleClient {\n        let _ = rustls::crypto::ring::default_provider().install_default();\n        CodewhaleClient::new(&Config {\n            provider: Some(\"zai\".to_string()),\n            api_key: Some(CONFIG_SECRET_SENTINELS[0].to_string()),\n            providers: Some(ProvidersConfig {\n                arcee: ProviderConfig {\n                    api_key: Some(CONFIG_SECRET_SENTINELS[1].to_string()),\n                    ..ProviderConfig::default()\n                },\n                moonshot: ProviderConfig {\n                    api_key: Some(CONFIG_SECRET_SENTINELS[2].to_string()),\n                    ..ProviderConfig::default()\n                },","sourceCodeStart":8285,"sourceCodeEnd":8321,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/client.rs#L8285-L8321","documentation":"A panic from `std::fs::write(...).expect(\"rotate fixture\")` — writing the rotated (account-B) auth.json failed. Same failure modes as the initial fixture write: permissions, missing directory, or full disk. It occurs after the client was already constructed, so only the rotation-phase write is affected.","triggerScenarios":"`std::fs::write(&path, rotated_json).expect(\"rotate fixture\")` fails on the canonicalized tempdir path mid-test (ENOENT after cleaner sweep, EACCES, ENOSPC).","commonSituations":"Tmp cleaner deleting the fixture directory mid-test, read-only temp mounts in CI containers, or disk exhaustion between the first and second write.","solutions":["Check free space and write access on the temp volume; probe with touch.","Disable tmp cleaners that race with the test (systemd-tmpfiles, tmpwatch).","Re-run with a fresh dedicated TMPDIR (mktemp -d) outside swept paths.","In containers, mount the temp dir as writable tmpfs and confirm ownership."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// rust, before the rotation write\nassert!(path.parent().map(|d| d.is_dir()).unwrap_or(false), \"fixture dir gone before rotation\");","typeGuard":null,"tryCatchPattern":"std::fs::write(&path, rotated)\n    .unwrap_or_else(|e| panic!(\"rotate fixture {path:?}: {e}\"));","preventionTips":["Same preflight as the initial write: writable temp volume, no cleaner races.","Re-check free space before multi-write tests on small CI disks.","Keep TempDir alive through the entire test body."],"tags":["rust","filesystem","io","test-fixture"],"backgroundTag":"file-write-failed","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T11:17:16.035Z"}