{"record":{"id":"cc759f506f67d540","repo":"aaif-goose/goose","slug":"failed-to-serialize-extension-state","errorCode":null,"errorMessage":"Failed to serialize extension state: {}","messagePattern":"Failed to serialize extension state: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/goose/src/agents/agent.rs","lineNumber":1283,"sourceCode":"            .extension_data(session_data.extension_data)\n            .apply()\n            .await?;\n\n        Ok(())\n    }\n\n    /// Save current extension state to session by session_id\n    pub async fn persist_extension_state(&self, session_id: &str) -> Result<()> {\n        let extensions_state =\n            EnabledExtensionsState::new(self.extension_configs_for_persistence().await);\n\n        let session_manager = self.config.session_manager.clone();\n        let session = session_manager.get_session(session_id, false).await?;\n        let mut extension_data = session.extension_data.clone();\n\n        extensions_state\n            .to_extension_data(&mut extension_data)\n            .map_err(|e| anyhow!(\"Failed to serialize extension state: {}\", e))?;\n\n        session_manager\n            .update(session_id)\n            .extension_data(extension_data)\n            .apply()\n            .await?;\n\n        Ok(())\n    }\n\n    /// Load extensions from session into the agent\n    /// Skips extensions that are already loaded\n    /// Uses the session's working_dir for extension initialization\n    pub async fn load_extensions_from_session(\n        self: &Arc<Self>,\n        session: &Session,\n    ) -> Vec<ExtensionLoadResult> {\n        let session_extensions =","sourceCodeStart":1265,"sourceCodeEnd":1301,"githubUrl":"https://github.com/aaif-goose/goose/blob/3810898a7447ec3299be72e223d3570a7aabf0ab/crates/goose/src/agents/agent.rs#L1265-L1301","documentation":"Same serialization step as save_extension_state, in the session_id-based variant Agent::persist_extension_state: EnabledExtensionsState::to_extension_data failed to turn the agent's enabled extensions into JSON for the session's extension_data. It fails before the session_manager.update(...).apply() write, so session state on disk is unchanged.","triggerScenarios":"Called after add_extension/remove_extension flows with an ExtensionConfig in the agent that serde cannot serialize; enum shape mismatch between the running binary and the stored config; programmatically-constructed extension config with invalid contents.","commonSituations":"Version-skew after upgrading goose with extensions enabled in existing sessions; third-party extension configs that don't round-trip through the current schema.","solutions":["Locate the unserializable extension (bisect by serializing configs one by one)","Update both goose and the extension to compatible versions","Remove the problematic extension from the agent and retry persist","Check the {e} message — it names the serde error and the failing field"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn extension_serialize_failed(e: &anyhow::Error) -> bool {\n    e.to_string().contains(\"Failed to serialize extension state\")\n}","tryCatchPattern":"if let Err(e) = agent.persist_extension_state(session_id).await {\n    if extension_serialize_failed(&e) {\n        // serialization (not storage) failed — session file is untouched;\n        // identify and remove the bad extension config\n    } else {\n        return Err(e);\n    }\n}","preventionTips":["Serialize extension configs in tests when introducing new ExtensionConfig variants","Avoid hand-constructing ExtensionConfig values that skip serde round-trips","Re-check extension lists after version upgrades"],"tags":["rust","goose","extensions","serialization"],"backgroundTag":null,"analyzedSha":"3810898a7447ec3299be72e223d3570a7aabf0ab","analyzedAt":"2026-08-16T10:14:26.282Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}