{"record":{"id":"4321ccb66d1fcdaf","repo":"nexu-io/open-design","slug":"no-volcengine-ark-api-key-configure-it-in-settin","errorCode":null,"errorMessage":"no Volcengine Ark API key — configure it in Settings or set ARK_API_KEY","messagePattern":"no Volcengine Ark API key — configure it in Settings or set ARK_API_KEY","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/media/index.ts","lineNumber":1400,"sourceCode":"    suggestedExt: format === 'opus' ? '.ogg' : `.${format}`,\n  };\n}\n\n// ---------------------------------------------------------------------------\n// Provider: Volcengine Ark — Doubao Seedance 2.0 video.\n//\n// Docs:\n//   POST /api/v3/contents/generations/tasks   → { id }\n//   GET  /api/v3/contents/generations/tasks/{id} → { status, content: { video_url } }\n// We submit, poll until succeeded/failed, then fetch the produced\n// video_url and return the raw bytes. The temporary URL Volcengine\n// returns is only valid for ~24h, so streaming the bytes into the\n// project folder is required to keep them addressable.\n// ---------------------------------------------------------------------------\n\nasync function renderVolcengineVideo(ctx: MediaContext, credentials: ProviderConfig, onProgress?: ProgressFn): Promise<RenderResult> {\n  if (!credentials.apiKey) {\n    throw new Error(\n      'no Volcengine Ark API key — configure it in Settings or set ARK_API_KEY',\n    );\n  }\n  const baseUrl = (credentials.baseUrl || 'https://ark.cn-beijing.volces.com/api/v3').replace(/\\/$/, '');\n\n  // Seedance accepts inline `--resolution`, `--duration`, `--ratio` and\n  // `--camerafixed` flags inside the prompt text. We append a flags\n  // suffix so user prompts that already contain them still win.\n  const ratio = volcengineRatioFor(ctx.aspect);\n  const durationSec = ctx.length || 5;\n  const resolution = '720p';\n  const promptText = (ctx.prompt && ctx.prompt.trim()) || 'A short cinematic clip.';\n  const suffixFlags: string[] = [];\n  if (!/--resolution\\b/.test(promptText)) suffixFlags.push(`--resolution ${resolution}`);\n  if (!/--duration\\b/.test(promptText)) suffixFlags.push(`--duration ${durationSec}`);\n  if (!/--ratio\\b/.test(promptText)) suffixFlags.push(`--ratio ${ratio}`);\n  const fullText = suffixFlags.length\n    ? `${promptText} ${suffixFlags.join(' ')}`","sourceCodeStart":1382,"sourceCodeEnd":1418,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/media/index.ts#L1382-L1418","documentation":"Thrown at the top of `renderVolcengineVideo` (Doubao Seedance) when no Volcengine Ark API key is available. The renderer cannot authenticate the `POST /api/v3/contents/generations/tasks` call, so it fails fast with an actionable message naming the `ARK_API_KEY` env var and the Settings UI.","triggerScenarios":"`credentials.apiKey` is falsy after `resolveProviderConfig('volcengine')` resolves the key from Settings, `ARK_API_KEY`, or media-config, while the selected model is a `provider: 'volcengine'` video model (e.g. `doubao-seedance-*`).","commonSituations":"(1) Fresh install where the user picked a Seedance model before adding a key; (2) `ARK_API_KEY` set in a different shell than the one running the daemon; (3) key cleared from Settings but model selection persisted.","solutions":["Set `ARK_API_KEY` in the daemon's environment (or export it in the shell that launches `tools-dev`), or enter the key under Settings → Providers → Volcengine.","Restart the daemon after adding the key so `resolveProviderConfig` re-reads it.","Confirm the selected model is actually a Volcengine model and not an aliased one routed elsewhere."],"exampleFix":"// before\n// (no key configured, Seedance model selected)\nod media generate --surface video --model doubao-seedance-1-0-t2v --prompt '...'\n\n// after\nexport ARK_API_KEY=sk-xxxx   # in the shell that runs tools-dev\nod media generate --surface video --model doubao-seedance-1-0-t2v --prompt '...'","handlingStrategy":"validation","validationCode":"function ensureVolcengineCreds(credentials: ProviderConfig): void {\n  if (!credentials.apiKey) {\n    throw new Error('no Volcengine Ark API key — configure it in Settings or set ARK_API_KEY');\n  }\n}\n// call before renderVolcengineVideo(ctx, credentials, onProgress)\nensureVolcengineCreds(credentials);","typeGuard":"function hasVolcengineCreds(c: ProviderConfig): c is ProviderConfig & { apiKey: string } {\n  return typeof c.apiKey === 'string' && c.apiKey.length > 0;\n}","tryCatchPattern":null,"preventionTips":["Set `ARK_API_KEY` in the shell that launches the daemon, not just your editor.","Restart the daemon after adding a key so `resolveProviderConfig` re-reads it.","Gate model selection on whether a Volcengine credential is configured."],"tags":["volcengine","ark","seedance","api-key","config"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}