OpenHands/OpenHands · error · Error

Conversation ${conversationId} was not found

Error message

Conversation ${conversationId} was not found

What it means

Thrown by requireAppConversation when a batchGetAppConversations call for a specific conversation ID returns null/undefined for that entry. This is a defensive guard in methods like updateConversationTitle and updateConversationRepository that fetch the conversation after mutating it, expecting it to exist. The error includes the conversationId in the message.

Source

Thrown at src/api/conversation-service/agent-server-conversation-service.api.ts:317

  "error",
  "stuck",
]);

function toRuntimeStatus(
  status: DirectConversationInfo["execution_status"],
): RuntimeConversationInfo["status"] {
  const nextStatus = status ?? "idle";
  return (
    RUNTIME_STATUSES.has(nextStatus) ? nextStatus : "idle"
  ) as RuntimeConversationInfo["status"];
}

function requireAppConversation(
  conversation: AppConversation | null | undefined,
  conversationId: string,
): AppConversation {
  if (!conversation) {
    throw new Error(`Conversation ${conversationId} was not found`);
  }
  return conversation;
}

/**
 * Options for {@link AgentServerConversationService.createConversation}.
 */
export interface CreateConversationOptions {
  initialUserMsg?: string;
  conversationInstructions?: string;
  plugins?: PluginSpec[];
  metadata?: ConversationMetadata | null;
  workingDirOverride?: string;
  workspaceMode?: WorkspaceMode;
  parentConversationId?: string;
  agentType?: "default" | "plan";
  sandboxId?: string;
  // Launch from a saved AgentProfile (resolved server-side) instead of the

View on GitHub (pinned to 500b4c533e)

Solutions

  1. Verify the conversation still exists before calling update methods: const [conv] = await batchGetAppConversations([id]); if (!conv) return;
  2. Handle the not-found case gracefully in the UI by redirecting to the home page.
  3. Check if the user switched backends, which would invalidate conversation IDs.

Example fix

// before
const updated = await AgentServerConversationService.updateConversationTitle(id, title);

// after: handle not-found
try {
  const updated = await AgentServerConversationService.updateConversationTitle(id, title);
} catch (e) {
  if (e instanceof Error && e.message.includes('was not found')) {
    navigate('/'); // redirect to home
    return;
  }
  throw e;
}
Defensive patterns

Strategy: validation

Validate before calling

async function conversationExists(id: string): Promise<boolean> {
  const [conv] = await AgentServerConversationService.batchGetAppConversations([id]);
  return conv != null;
}

// Before title/repository update:
if (!(await conversationExists(id))) {
  navigate('/'); // redirect to home
  return;
}

Type guard

function isConversationNotFound(e: unknown): boolean {
  return e instanceof Error && /was not found/.test(e.message);
}

Try / catch

try {
  await AgentServerConversationService.updateConversationTitle(id, title);
} catch (error) {
  if (error instanceof Error && error.message.includes('was not found')) {
    navigate('/');
    return;
  }
  throw error;
}

Prevention

When it happens

Trigger: updateConversationTitle or updateConversationRepository is called with a conversationId that doesn't exist on the agent-server. The mutation (title update or metadata write) may succeed locally, but the subsequent batchGetAppConversations lookup returns null because the server doesn't have that conversation.

Common situations: Conversation was deleted by another session or tab between the title edit and the fetch; the conversationId in the URL is stale (from a bookmarked link to a deleted conversation); the agent-server was reset/reinstalled losing conversation state; a cloud-to-local backend switch caused the conversation to not exist on the new backend.

Related errors


AI-assisted analysis of OpenHands/OpenHands@500b4c533e (2026-08-12). Data as JSON: /api/errors/19c75bbceb29dc98. Report an issue: GitHub.