Skip to content

Cloudflare host: v1.6.7 fails every execute with "StorageError: Failed to decrypt secret" despite unchanged EXECUTOR_SECRET_KEY (regression from #1867?) #1896

Description

@ArnelBukva

Summary

On the self-hosted Cloudflare host, upgrading from v1.6.3 to v1.6.7 breaks every execute tool call with Internal tool error / StorageError: Failed to decrypt secret — even when EXECUTOR_SECRET_KEY is verifiably unchanged. Rolling the Worker version back to the v1.6.3 build (same key, same D1, same Access config) fixes it instantly. Discovery calls (tools.search, tools.describe, connections.list) keep working on v1.6.7, which makes a post-deploy smoke test pass while every real upstream call fails.

Environment

  • Host: apps/host-cloudflare (single Worker, D1 storage, Cloudflare Access in front, per docs/hosted/cloudflare)
  • Working version: v1.6.3
  • Broken version: v1.6.7 (also reproduced on a build deployed via wrangler deploy with the EXECUTOR_SECRET_KEY step of deploy.sh removed, to rule out key rotation)
  • Client: MCP over streamable HTTP through Cloudflare Access Managed OAuth (claude.ai / Claude Code connector)

Reproduction

  1. Running v1.6.3, verify a real call works, e.g. execute with return await tools.context7_docs.org.context7.resolve_library_id({ libraryName: 'react', query: 'react' })ok: true.
  2. Deploy v1.6.7 without touching secrets (vite build && wrangler deploy; wrangler secret list confirms EXECUTOR_SECRET_KEY present and untouched).
  3. The same call now fails with Internal tool error [ref]. Failures persist ≥5 minutes after deploy and reproduce across two separate MCP connections, so it is not version-propagation lag.
  4. wrangler rollback to the v1.6.3 version id → the same call passes immediately.

Captured error (wrangler tail, v1.6.7, original key)

ERROR: tool dispatch failed StorageError: Failed to decrypt secret
    at Object.catch (worker.js:212235:44)
    at worker.js:5752:55
    at ~effect/Utils/internal (worker.js:2264:16)
    at executor.tool.execute (worker.js:163589:22)
    at mcp.tool.dispatch (worker.js:167182:20)
    at mcp.tool.dispatch (definition) (worker.js:166491:26)
    at executor.tool.rpc_dispatch (worker.js:216857:9)
    at executor.code.exec.dynamic_worker (worker.js:217009:3)
    at executor.code.exec (worker.js:167250:63)
    at mcp.execute (worker.js:191052:35)

with cause Error: Authentication failed at Decipheriv.final.

Analysis

packages/plugins/encrypted-secrets is unchanged between v1.6.3 and v1.6.7 (version bumps only), and the same key decrypts the same stored credentials fine on v1.6.3. The one substantive change in v1.6.7 is 98d6c6a "Run independent tool-call reads concurrently" (#1867), which rewrites the sdk executor's read scheduling (~400 lines in packages/core/sdk/src/executor.ts). The symptom is consistent with concurrent/speculative reads racing the secret read/decrypt path.

A second, separate foot-gun hit during the same upgrade

deploy.sh's "Ensuring EXECUTOR_SECRET_KEY" step decides whether the key exists via bunx wrangler secret list 2>/dev/null | grep -q EXECUTOR_SECRET_KEY. If wrangler secret list fails transiently (stderr is discarded), the grep is empty and the script silently generates a new key over the existing one, making every stored credential undecryptable. That happened to us on this upgrade before we isolated the bug above. Consider failing hard when secret list errors instead of falling through to key generation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions