{"record":{"id":"609abe80e4cae97e","repo":"Hmbown/CodeWhale","slug":"bounded-provider-catalog-cache-exceeds-its-write-limit","errorCode":null,"errorMessage":"bounded provider catalog cache exceeds its write limit","messagePattern":"bounded provider catalog cache exceeds its write limit","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/tui/src/provider_catalog_live.rs","lineNumber":864,"sourceCode":"    while persisted_envelope_len(&cache)? > limits.max_bytes {\n        let _removed_rows = evict_next(&mut cache)?;\n    }\n\n    Ok(cache)\n}\n\nfn write_bounded_cache(\n    path: &Path,\n    cache: ProviderCatalogCache,\n    protected_scope: Option<(&str, &str)>,\n    limits: CachePersistenceLimits,\n) -> Result<()> {\n    let cache = bounded_cache_for_persistence(cache, protected_scope, now_unix(), limits)?;\n    let envelope = PersistedProviderCatalogs {\n        schema_version: CACHE_SCHEMA_VERSION,\n        cache,\n    };\n    anyhow::ensure!(\n        persisted_envelope_len(&envelope.cache)? <= limits.max_bytes,\n        \"bounded provider catalog cache exceeds its write limit\"\n    );\n    atomic_write_json(path, &envelope)\n}\n\nfn persist_scope(cache: &ProviderCatalogCache, provider: &str, fingerprint: &str) -> bool {\n    let Some(path) = cache_path() else {\n        return false;\n    };\n    let provider = canonical_provider_scope(provider);\n    let result = (|| -> Result<()> {\n        let lock_file = open_cache_lock(&cache_lock_path(&path))?;\n        let mut lock = fd_lock::RwLock::new(lock_file);\n        let _guard = lock\n            .write()\n            .with_context(|| format!(\"write-lock provider catalog cache {}\", path.display()))?;\n        // Merge only the exact scope this process just changed into the latest","sourceCodeStart":846,"sourceCodeEnd":882,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/provider_catalog_live.rs#L846-L882","documentation":"write_bounded_cache serializes the bounded cache into a PersistedProviderCatalogs envelope and re-checks that the final JSON size fits limits.max_bytes before the atomic write. If the whole envelope still exceeds the byte budget after bounding, persistence is refused rather than writing an oversized file.","triggerScenarios":"Calling persist_scope/persist_failure_scope (or the round-trip test) when, after bounded_cache_for_persistence compaction and schema_version envelope wrapping, the serialized cache exceeds limits.max_bytes.","commonSituations":"Many scopes each near the per-scope limit whose combined size blows the total budget; a stale large cache being persisted with new, smaller limits.","solutions":["Shrink the cache before persisting (evict stale/failed scopes) so the envelope fits","Increase limits.max_bytes for the persistence config","Write only the protected/essential scopes instead of the full cache","Clear the on-disk cache file and let the app rebuild a smaller cache"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if persisted_envelope_len(&cache)? > limits.max_bytes {\n    // evict stale scopes or raise limits before calling write_bounded_cache\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = write_bounded_cache(&path, &cache, protected, limits) {\n    if e.to_string().contains(\"exceeds its write limit\") {\n        // fall back to persisting only the protected scope\n        write_bounded_cache(&path, &protected_only, None, limits)?;\n    } else { return Err(e); }\n}","preventionTips":["Budget total cache size across scopes, not just per scope","Evict failed/stale scopes before persisting","Raise limits.max_bytes deliberately if caches are legitimately large","Delete an oversized cache file and let it rebuild smaller"],"tags":["cache","limits","persistence","size-limit"],"backgroundTag":"file-size-limit-exceeded","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}