OpenHands / OpenHands/OpenHands

Canvas (cloud/SaaS): verification confirm & compact-context buttons raise HTTP 405

Open
#17,510 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

agent-canvas bug cloud priority:medium release-note-required
Dominant language
TypeScript
Stars
88.5k
Forks
11.6k
Avg merge
2d 22h
Merged PRs (30d)
189

Description

Summary

In prod and staging (launched from openhands/saas-deploy), the Agent Canvas UI at app.all-hands.dev/canvas returns HTTP 405 when the user clicks:

  • the verification confirm button (confirmation mode), and
  • the compact context (condense) button.

The legacy UI at app.all-hands.dev/ does not have this problem — the same buttons work there.

Root cause

This is not a CORS issue (initial suspicion). It is a missing route.

In cloud mode the Canvas frontend routes every agent-server runtime call through a POST /api/cloud-proxy envelope on the cloud backend, with the per-conversation runtime URL passed as hostOverride. That /api/cloud-proxy route does not exist on the saas-deploy backend, so every runtime-scoped call returns 405 Method Not Allowed.

The legacy openhands/openhands UI works because it calls the runtime directly with the X-Session-API-Key header — it never goes through /api/cloud-proxy.

The runtime's CORS allowlist (OH_ALLOW_CORS_ORIGINS, already set to the Canvas origin in saas-deploy) permits direct browser→runtime calls, so the proxy hop is unnecessary. Canvas was dealing with runtime calls differently from the legacy UI, which is why only Canvas broke.

Affected runtime calls (all routed via /api/cloud-proxy → 405)

  • respondToConfirmation (verification confirm)
  • condenseConversation (compact context)
  • sendMessage / sendEvent
  • bash event reads (listOutputs)
  • executeCommand
  • downloadFile
  • getGitCommits / commit-changes / commit-diff

Proposed fix

Collapse each cloud runtime branch onto the same direct typed-client path local mode already uses (ConversationClient / BashClient / RemoteWorkspace / FileClient / HttpClient pointed at the per-conversation runtime URL, authenticated with the session API key). The runtime CORS allowlist already permits the cross-origin call.

App-API-only calls that have no per-conversation runtime host (event history search, git changes/diff listing, profile/acp-model switches) keep using callCloudProxy against the cloud backend host — those are not runtime calls and are not affected.

This is the "easy fix" alternative to the heavier enterprise-side approach in https://github.com/OpenHands/enterprise/pull/424.

Environment

  • Frontend: app.all-hands.dev/canvas (Agent Canvas)
  • Backend: openhands/saas-deploy (prod + staging)
  • Legacy UI app.all-hands.dev/ unaffected

This issue was created by an AI agent (OpenHands) on behalf of the user.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the Canvas cloud runtime branches for respondToConfirmation, condenseConversation, sendMessage, and the other listed runtime calls, comparing them with the local ConversationClient, BashClient, RemoteWorkspace, FileClient, and HttpClient paths. Done means runtime calls use the per-conversation URL with the session API key and no longer return 405, while app-API-only calls continue using callCloudProxy.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
api, cloud, frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
62/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.