{"record":{"id":"7fbbb6a1fe661aa6","repo":"vercel/ai","slug":"custom-network-policy-requires-at-least-one-of-all","errorCode":null,"errorMessage":"Custom network policy requires at least one of allowedHosts, allowedCIDRs, or deniedCIDRs to be non-empty.","messagePattern":"Custom network policy requires at least one of allowedHosts, allowedCIDRs, or deniedCIDRs to be non-empty\\.","errorType":"exception","errorClass":"HarnessCapabilityUnsupportedError","httpStatus":null,"severity":"error","filePath":"packages/sandbox-vercel/src/vercel-network-policy-manager.ts","lineNumber":288,"sourceCode":"\nfunction toNetworkAccessPolicy(\n  policy: HarnessV1NetworkPolicy,\n): NetworkAccessPolicy {\n  switch (policy.mode) {\n    case 'allow-all':\n      return { mode: 'allow-all' };\n    case 'deny-all':\n      return { mode: 'deny-all' };\n    case 'custom': {\n      const allowedHosts = [...(policy.allowedHosts ?? [])];\n      const allowedCIDRs = [...(policy.allowedCIDRs ?? [])];\n      const deniedCIDRs = [...(policy.deniedCIDRs ?? [])];\n      if (\n        allowedHosts.length === 0 &&\n        allowedCIDRs.length === 0 &&\n        deniedCIDRs.length === 0\n      ) {\n        throw createPolicyConflictError(\n          'Custom network policy requires at least one of allowedHosts, allowedCIDRs, or deniedCIDRs to be non-empty.',\n        );\n      }\n      return {\n        mode: 'custom',\n        allowedHosts,\n        allowedCIDRs,\n        deniedCIDRs,\n      };\n    }\n  }\n}\n\nfunction composeNetworkPolicy({\n  accessPolicy,\n  requestTransformations,\n  forwardRules,\n}: {","sourceCodeStart":270,"sourceCodeEnd":306,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/sandbox-vercel/src/vercel-network-policy-manager.ts#L270-L306","documentation":"toNetworkAccessPolicy validates HarnessV1NetworkPolicy objects with mode 'custom'. A custom policy that specifies none of allowedHosts, allowedCIDRs, or deniedCIDRs would produce an empty custom rule set, which is meaningless and dangerous (it neither allows nor clearly denies anything), so the manager throws HarnessCapabilityUnsupportedError. Use 'allow-all' or 'deny-all' modes for blanket behavior instead.","triggerScenarios":"Calling setNetworkPolicy({ mode: 'custom' }) where allowedHosts, allowedCIDRs, and deniedCIDRs are all undefined, null, or empty arrays.","commonSituations":"Building the policy object dynamically from config/env where all lists end up empty; a refactor that renamed fields so the intended values no longer populate the expected keys; copying an example and forgetting to fill allowedHosts.","solutions":["Provide at least one entry: add hostnames to allowedHosts, or CIDR ranges to allowedCIDRs/deniedCIDRs.","If you intend to allow all traffic, pass { mode: 'allow-all' } instead of an empty custom policy.","If you intend to block all traffic, pass { mode: 'deny-all' }.","Validate your config before constructing the policy so empty lists fall back to an explicit mode."],"exampleFix":"// before\nawait manager.setNetworkPolicy({ mode: 'custom', allowedHosts: [], allowedCIDRs: [], deniedCIDRs: [] });\n// after\nawait manager.setNetworkPolicy({ mode: 'custom', allowedHosts: ['api.example.com'] });","handlingStrategy":"validation","validationCode":"function validateNetworkPolicy(policy: { mode: string; allowedHosts?: string[]; allowedCIDRs?: string[]; deniedCIDRs?: string[] }) {\n  if (policy.mode !== 'custom') return; // allow-all / deny-all are fine\n  const empty =\n    (policy.allowedHosts ?? []).length === 0 &&\n    (policy.allowedCIDRs ?? []).length === 0 &&\n    (policy.deniedCIDRs ?? []).length === 0;\n  if (empty) throw new Error('custom policy needs allowedHosts, allowedCIDRs, or deniedCIDRs');\n}\nvalidateNetworkPolicy(policy);\nawait manager.setNetworkPolicy(policy);","typeGuard":"function isUsableCustomPolicy(p: { mode: string; allowedHosts?: readonly string[]; allowedCIDRs?: readonly string[]; deniedCIDRs?: readonly string[] }): boolean {\n  return p.mode !== 'custom' ||\n    (p.allowedHosts?.length ?? 0) + (p.allowedCIDRs?.length ?? 0) + (p.deniedCIDRs?.length ?? 0) > 0;\n}","tryCatchPattern":"try {\n  await manager.setNetworkPolicy(policy);\n} catch (error) {\n  if (error instanceof HarnessCapabilityUnsupportedError && /requires at least one of/.test(error.message)) {\n    await manager.setNetworkPolicy({ mode: 'deny-all' }); // safe explicit fallback\n  } else throw error;\n}","preventionTips":["Use 'allow-all' or 'deny-all' modes when you don't need fine-grained rules.","Load policy lists from config with explicit defaults and assert non-emptiness for custom mode.","Add a unit test asserting isUsableCustomPolicy for every policy your app constructs.","Watch for refactors that rename allowedHosts/allowedCIDRs/deniedCIDRs and silently leave them empty."],"tags":["vercel-sandbox","network-policy","validation","configuration"],"backgroundTag":"empty-network-policy","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}