aaif-goose/goose · error

Failed to serialize extension state: {}

Error message

Failed to serialize extension state: {}

What it means

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.

Source

Thrown at crates/goose/src/agents/agent.rs:1283

            .extension_data(session_data.extension_data)
            .apply()
            .await?;

        Ok(())
    }

    /// Save current extension state to session by session_id
    pub async fn persist_extension_state(&self, session_id: &str) -> Result<()> {
        let extensions_state =
            EnabledExtensionsState::new(self.extension_configs_for_persistence().await);

        let session_manager = self.config.session_manager.clone();
        let session = session_manager.get_session(session_id, false).await?;
        let mut extension_data = session.extension_data.clone();

        extensions_state
            .to_extension_data(&mut extension_data)
            .map_err(|e| anyhow!("Failed to serialize extension state: {}", e))?;

        session_manager
            .update(session_id)
            .extension_data(extension_data)
            .apply()
            .await?;

        Ok(())
    }

    /// Load extensions from session into the agent
    /// Skips extensions that are already loaded
    /// Uses the session's working_dir for extension initialization
    pub async fn load_extensions_from_session(
        self: &Arc<Self>,
        session: &Session,
    ) -> Vec<ExtensionLoadResult> {
        let session_extensions =

View on GitHub (pinned to 3810898a74)

Solutions

  1. Locate the unserializable extension (bisect by serializing configs one by one)
  2. Update both goose and the extension to compatible versions
  3. Remove the problematic extension from the agent and retry persist
  4. Check the {e} message — it names the serde error and the failing field
Defensive patterns

Strategy: try-catch

Type guard

fn extension_serialize_failed(e: &anyhow::Error) -> bool {
    e.to_string().contains("Failed to serialize extension state")
}

Try / catch

if let Err(e) = agent.persist_extension_state(session_id).await {
    if extension_serialize_failed(&e) {
        // serialization (not storage) failed — session file is untouched;
        // identify and remove the bad extension config
    } else {
        return Err(e);
    }
}

Prevention

When it happens

Trigger: 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.

Common situations: Version-skew after upgrading goose with extensions enabled in existing sessions; third-party extension configs that don't round-trip through the current schema.

Related errors


AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16). Data as JSON: /api/errors/cc759f506f67d540. Report an issue: GitHub.