Skip to content

feat(sandbox): surface validation reason on /config 400#3294

Open
tlgimenes wants to merge 1 commit intomainfrom
tlgimenes/sandbox-config-error-detail
Open

feat(sandbox): surface validation reason on /config 400#3294
tlgimenes wants to merge 1 commit intomainfrom
tlgimenes/sandbox-config-error-detail

Conversation

@tlgimenes
Copy link
Copy Markdown
Contributor

@tlgimenes tlgimenes commented May 6, 2026

What is this contribution about?

The daemon's `TenantConfigStore` was discarding the field-level `reason` produced by `validateTenantConfig` (e.g. `runtime invalid: python`, `git.repository.cloneUrl is empty`) and returning only the bare `"invalid"` rejection constant — so a 400 from `POST /_decopilot_vm/config` came back as the opaque `{"error":"invalid"}` with no way to tell which field failed without attaching a debugger. This PR forwards `validation.reason` as the rejection `detail` so the wire response becomes `{"error":"invalid: "}`, logs the same line via `console.warn` so it lands in pod logs, and additionally preserves the thrown error message under the `apply-failed` rejection so unexpected exceptions in the apply queue stop being silently flattened.

How to Test

  1. Boot a sandbox and POST a deliberately bad config (e.g. `{"application": {"runtime": "python"}}`)
  2. Expected: response is `HTTP 400 {"error":"invalid: runtime invalid: python"}` (was previously `{"error":"invalid"}`)
  3. Pod logs show `[config-store] rejected payload as invalid: runtime invalid: python`
  4. `bun run check` and `bun test packages/sandbox/server packages/sandbox/daemon/config-store` pass

Migration Notes

None. The wire shape stays `{"error": string}` with status 400; only the string content gets richer.

Review Checklist

  • PR title is clear and descriptive
  • Changes are tested and working
  • No breaking changes

Summary by cubic

Surface field-level validation reasons in 400 responses from /_decopilot_vm/config and log them for easier debugging. Also keep thrown error messages when apply fails so failures aren’t silently flattened.

  • Bug Fixes
    • Forward validateTenantConfig reason as rejection detail so clients see {"error":"invalid: <reason>"}.
    • Log invalid payloads and apply exceptions via console.warn for pod visibility.
    • Preserve the thrown error message under the apply-failed rejection.

Written for commit c2e305f. Summary will update on new commits.

The TenantConfigStore was discarding the field-level reason produced by
validateTenantConfig (e.g. "runtime invalid: python", "git.repository.cloneUrl
is empty") and returning the bare "invalid" rejection constant. The wire
response was always {"error":"invalid"} with no field detail, so a 400 from
/_decopilot_vm/config was undiagnosable without attaching a debugger.

Pass validation.reason as the rejection detail so the route handler emits
{"error":"invalid: <reason>"}, and log on the daemon side for pod logs. Also
preserve the message from any unexpected exception in the apply queue under
the apply-failed rejection so those don't get silently flattened either.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

Release Options

Suggested: Minor (2.306.0) — based on feat: prefix

React with an emoji to override the release type:

Reaction Type Next Version
👍 Prerelease 2.305.1-alpha.1
🎉 Patch 2.305.1
❤️ Minor 2.306.0
🚀 Major 3.0.0

Current version: 2.305.0

Note: If multiple reactions exist, the smallest bump wins. If no reactions, the suggested bump is used (default: patch).

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 6, 2026

🧪 Benchmark

Should we run the Virtual MCP strategy benchmark for this PR?

React with 👍 to run the benchmark.

Reaction Action
👍 Run quick benchmark (10 & 128 tools)

Benchmark will run on the next push after you react.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant