aaif-goose/goose · error

Message with id ${messageId} not found in current messages

Error message

Message with id ${messageId} not found in current messages

What it means

Thrown by the message-edit path in chatSessionController when the message id submitted for edit is not present in the current UI snapshot's messages array. The controller re-reads the live snapshot at submit time (options.getCurrentSnapshot()), so the id the caller captured earlier (e.g. from a rendered list) can be stale. It also falls back to nothing — there is no storedSnapshot lookup for the message itself.

Source

Thrown at ui/desktop/src/acp/chatSessionController.ts:258

async function updateMessage(
  sessionId: string,
  messageId: string,
  newContent: string,
  editType: 'fork' | 'edit',
  retainedImages: ImageData[],
  options: AcpSubmitMessageOptions
): Promise<void> {
  assertNoPendingPromptCancellation(sessionId);

  const currentSnapshot = options.getCurrentSnapshot();
  const storedSnapshot = acpChatSessionStore.getSnapshot(sessionId);
  const activePromptAttemptId = storedSnapshot?.activePromptAttemptId;
  const currentMessages = currentSnapshot?.messages ?? [];
  const message = currentMessages.find((m) => m.id === messageId);

  if (!message) {
    throw new Error(`Message with id ${messageId} not found in current messages`);
  }

  if (editType === 'fork') {
    await forkSessionWithEditedMessage(sessionId, message, newContent, retainedImages);
    return;
  }

  const editSnapshot = currentSnapshot ?? storedSnapshot;
  const isPendingToolPermission =
    editSnapshot?.chatState === ChatState.WaitingForUserInput &&
    getPendingToolConfirmationIds(editSnapshot?.messages ?? []).size > 0;
  const isIdle = editSnapshot?.chatState === ChatState.Idle;
  const pendingToolPermissionPromptAttemptId = isPendingToolPermission
    ? activePromptAttemptId
    : undefined;
  const canEditInPlace = isIdle || pendingToolPermissionPromptAttemptId != null;

  if (!canEditInPlace) {

View on GitHub (pinned to 3810898a74)

Solutions

  1. Pass the message id from the same snapshot you got it from, re-read immediately before calling submit.
  2. Ensure the edit UI is disabled for messages that no longer exist (derive the editable list from the live snapshot).
  3. Verify the sessionId matches the snapshot store entry — a mismatched session yields an empty currentMessages array.
  4. Treat this error as a no-op UX signal (message gone) rather than a hard failure where appropriate.

Example fix

// before
const message = currentMessages.find((m) => m.id === messageId);
if (!message) {
  throw new Error(`Message with id ${messageId} not found in current messages`);
}

// after (caller refreshes state and degrades gracefully)
const snapshot = options.getCurrentSnapshot();
const message = (snapshot?.messages ?? []).find((m) => m.id === messageId);
if (!message) {
  console.warn(`Message ${messageId} no longer present; ignoring edit`);
  return; // or re-render from the fresh snapshot and re-prompt the user
}
Defensive patterns

Strategy: validation

Validate before calling

// Verify the message is still present in the live snapshot before submitting an edit
function canEditMessage(snapshot: { messages: { id: string }[] } | undefined, messageId: string): boolean {
  return Boolean(snapshot?.messages.some((m) => m.id === messageId));
}

if (!canEditMessage(options.getCurrentSnapshot(), messageId)) {
  return; // message already gone; nothing to edit
}

Type guard

function findEditableMessage(
  messages: { id: string }[],
  messageId: string
): { id: string } | undefined {
  return messages.find((m) => m.id === messageId);
}

Try / catch

try {
  await submitEditedMessage(sessionId, messageId, newContent, retainedImages, options);
} catch (error) {
  if (/not found in current messages/.test(String(error))) {
    // Stale UI: refresh from the store and drop the edit silently
    refreshFromSnapshot(sessionId);
    return;
  }
  throw error;
}

Prevention

When it happens

Trigger: Submitting an edit for a message that was removed because the session was reset, cleared, or switched between render and submit; using a message id from a previous session id; a fork/branch operation replaced the message list; concurrent edit where another action already truncated the conversation.

Common situations: User opens the edit dialog, then the agent finishes and UI reconciles messages, then submits; message ids persisted in component state across a session switch; tests calling the edit API with fabricated ids.

Related errors


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