zed-industries/zed · error

not supported

Error message

not supported

What it means

rewind() depends on connection.truncate(&self.session_id, cx) returning Some(truncate). When the connected agent does not implement session truncation, it returns None and rewind fails immediately with 'not supported'. This is a backend capability gap, not a data problem — restore_checkpoint is the git-backed alternative.

Source

Thrown at crates/acp_thread/src/acp_thread.rs:4024

                git_store
                    .update(cx, |git, cx| git.restore_checkpoint(checkpoint, cx))
                    .await?;
            }

            Ok(())
        })
    }

    /// Rewinds this thread to before the entry at `index`, removing it and all
    /// subsequent entries while rejecting any action_log changes made from that point.
    /// Unlike `restore_checkpoint`, this method does not restore from git.
    pub fn rewind(
        &mut self,
        client_id: ClientUserMessageId,
        cx: &mut Context<Self>,
    ) -> Task<Result<()>> {
        let Some(truncate) = self.connection.truncate(&self.session_id, cx) else {
            return Task::ready(Err(anyhow!("not supported")));
        };

        Self::flush_streaming_text(&mut self.streaming_text_buffer, cx);
        let telemetry = ActionLogTelemetry::from(&*self);
        cx.spawn(async move |this, cx| {
            cx.update(|cx| truncate.run(client_id.clone(), cx)).await?;
            this.update(cx, |this, cx| {
                if let Some((ix, _)) = this.user_message_mut(&client_id) {
                    // Collect all terminals from entries that will be removed
                    let terminals_to_remove: Vec<acp::TerminalId> = this.entries[ix..]
                        .iter()
                        .flat_map(|entry| entry.terminals())
                        .filter_map(|terminal| terminal.read(cx).id().clone().into())
                        .collect();

                    let range = ix..this.entries.len();
                    this.entries.truncate(ix);
                    cx.emit(AcpThreadEvent::EntriesRemoved(range));

View on GitHub (pinned to bc538def45)

Solutions

  1. Use restore_checkpoint instead — it rewinds entries and restores the git working tree
  2. Feature-check truncate support before showing the rewind affordance in the client
  3. Update the agent implementation to support session truncate
Defensive patterns

Strategy: type-guard

Validate before calling

// Feature-check truncate support before offering rewind
let supports_truncate = agent
    .connection()
    .truncate(&session_id, cx)
    .is_some();
rewind_button.set_visible(supports_truncate);

Type guard

fn connection_supports_rewind(agent: &Agent, session_id: &acp::SessionId, cx: &App) -> bool {
    agent.connection().truncate(session_id, cx).is_some()
}

Try / catch

let task = thread.update(cx, |thread, cx| thread.rewind(client_id.clone(), cx));
match task.await {
    Err(error) if error.to_string().contains("not supported") => {
        // Fall back to the git-backed path, which also rewinds entries.
        return thread.update(cx, |thread, cx| {
            thread.restore_checkpoint(client_id.clone(), cx)
        }).await;
    }
    other => other?,
}

Prevention

When it happens

Trigger: Calling rewind on a session whose ACP connection does not advertise/implement truncate: a third-party agent that never implemented session/truncate, or an agent speaking an older protocol version.

Common situations: Using Zed's agent panel against an external ACP agent lacking truncate support; version mismatch after updating one side; UI offers rewind because a checkpoint exists even though the connection cannot truncate.

Related errors


AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16). Data as JSON: /api/errors/de27cf4a0beba12e. Report an issue: GitHub.