{"record":{"id":"2c1ad94e47f338e3","repo":"vercel/ai","slug":"cannot-add-request-transformations-because-the-cur","errorCode":null,"errorMessage":"Cannot add request transformations because the current Vercel Sandbox policy contains request transformations that cannot be attributed to this call. Their header values are redacted, so preserving them safely is not possible.","messagePattern":"Cannot add request transformations because the current Vercel Sandbox policy contains request transformations that cannot be attributed to this call\\. Their header values are redacted, so preserving them safely is not possible\\.","errorType":"exception","errorClass":"HarnessCapabilityUnsupportedError","httpStatus":null,"severity":"error","filePath":"packages/sandbox-vercel/src/vercel-network-policy-manager.ts","lineNumber":128,"sourceCode":"          requestTransformations: incomingTransformations,\n          forwardRules: inspection.forwardRules,\n        });\n        const incomingHosts = getRequestTransformationHosts(incomingPolicy);\n\n        /*\n         * Vercel redacts transformed header values when a policy is read back.\n         * It can also normalize rule details, so initialization and resume can\n         * only attribute existing transformations by their materialized hosts.\n         * External transformations for the same hosts are indistinguishable\n         * and are necessarily treated as managed by this call.\n         */\n        if (\n          !isHostSetSubset({\n            subset: inspection.requestTransformationHosts,\n            superset: incomingHosts,\n          })\n        ) {\n          throw createPolicyConflictError(\n            'Cannot add request transformations because the current Vercel Sandbox policy contains request transformations that cannot be attributed to this call. Their header values are redacted, so preserving them safely is not possible.',\n          );\n        }\n      }\n\n      await this.#applyState({\n        accessPolicy: inspection.accessPolicy,\n        requestTransformations:\n          this.#state == null\n            ? incomingTransformations\n            : mergeRequestTransformations({\n                existing: this.#state.requestTransformations,\n                incoming: incomingTransformations,\n              }),\n        forwardRules: inspection.forwardRules.map(cloneForwardRule),\n        currentPolicy: inspection.currentPolicy,\n      });\n    });","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/sandbox-vercel/src/vercel-network-policy-manager.ts#L110-L146","documentation":"addRequestTransformations() on an uninitialized manager (no private state) must attribute transformations already present in the live Vercel policy. Because Vercel redacts transformed header values on read-back, existing transformations can only be matched by their materialized hosts. If the live policy has transformation hosts that are NOT covered by the hosts implied by the incoming transformations, the manager cannot tell which are yours and refuses with HarnessCapabilityUnsupportedError to avoid corrupting them.","triggerScenarios":"First mutation on a fresh VercelNetworkPolicyManager is addRequestTransformations(), while sandbox.currentSession().networkPolicy contains request transformations for hosts outside the set of hosts derivable from the incoming transformations (isHostSetSubset fails).","commonSituations":"Resuming a sandbox that already has transformations for other hosts (from a prior deployment/run); adding transformations for a narrower host list than what exists; direct @vercel/sandbox policy edits that added extra transformation rules behind the manager's back.","solutions":["Include transformations covering all existing transformation hosts in the incoming set (so incomingHosts is a superset of the live hosts), then call addRequestTransformations().","Use setRequestTransformations() instead to explicitly declare the complete desired set, replacing whatever exists.","Inspect sandbox.currentSession().networkPolicy to list existing transformation hosts and decide whether to adopt or replace them.","If the stale transformations are unwanted, replace the policy wholesale with setRequestTransformations([]) plus your new entries."],"exampleFix":"// before: only covers api.example.com while policy also has cdn.example.com transformations\nawait manager.addRequestTransformations([{ host: 'api.example.com', setHeaders: { 'x-key': '...' } }]);\n// after: cover all existing hosts, or declare full set\nawait manager.setRequestTransformations([\n  { host: 'api.example.com', setHeaders: { 'x-key': '...' } },\n  { host: 'cdn.example.com', setHeaders: { 'x-key': '...' } },\n]);","handlingStrategy":"validation","validationCode":"// ensure incoming transformation hosts cover all existing ones before adding\nfunction transformationHostsFromPolicy(p: unknown): string[] {\n  if (p == null || typeof p !== 'object') return [];\n  return ((p as any).rules ?? [])\n    .flatMap((r: any) => (r.requestTransformations ?? []).map(() => r.host))\n    .filter(Boolean);\n}\nconst existing = transformationHostsFromPolicy(sandbox.currentSession().networkPolicy);\nconst incoming = new Set(transformations.map(t => t.host));\nif (!existing.every(h => incoming.has(h))) {\n  // use setRequestTransformations() to replace, or extend incoming set\n  await manager.setRequestTransformations(transformations);\n} else {\n  await manager.addRequestTransformations(transformations);\n}","typeGuard":"function canAttributeTransformations(existingHosts: readonly string[], incomingHosts: readonly string[]): boolean {\n  const set = new Set(incomingHosts);\n  return existingHosts.every(h => set.has(h));\n}","tryCatchPattern":"try {\n  await manager.addRequestTransformations(transformations);\n} catch (error) {\n  if (error instanceof HarnessCapabilityUnsupportedError) {\n    // fall back to full explicit replacement\n    await manager.setRequestTransformations(transformations);\n  } else throw error;\n}","preventionTips":["On resume, list existing transformation hosts from the live policy and include all of them in the add call, or use setRequestTransformations().","Prefer setRequestTransformations() as the first mutation; use addRequestTransformations() only after the manager is initialized.","Avoid mixing direct @vercel/sandbox policy writes with manager operations.","Keep a record of transformation hosts your app created so resume flows can redeclare them."],"tags":["vercel-sandbox","network-policy","request-transformation","conflict"],"backgroundTag":"policy-conflict-redacted-values","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}