{"record":{"id":"a0806ce4d64d41b0","repo":"jackwener/OpenCLI","slug":"video-id-json-stringify-payload-sli","errorCode":null,"errorMessage":"提交抖音上传响应缺少 video id: ${JSON.stringify(payload).slice(0, 500)}","messagePattern":"提交抖音上传响应缺少 video id: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/douyin/_shared/vod-upload.js","lineNumber":202,"sourceCode":"    body,\n    headers: { 'content-type': 'application/json;charset=UTF-8' },\n  });\n  const res = await fetch(url, { method: 'POST', headers, body, signal: AbortSignal.timeout(30000) });\n  const text = await res.text();\n  let payload;\n  try {\n    payload = JSON.parse(text);\n  } catch {\n    throw new CommandExecutionError(`提交抖音上传失败，非 JSON 响应: HTTP ${res.status} ${text.slice(0, 300)}`);\n  }\n  const error = payload?.ResponseMetadata?.Error;\n  if (!res.ok || error) {\n    throw new CommandExecutionError(`提交抖音上传失败: HTTP ${res.status} ${JSON.stringify(error ?? payload)}`);\n  }\n  const result = payload?.Result?.Results?.[0] ?? payload?.Result ?? {};\n  const videoId = result.Vid ?? result.VideoId ?? result.VideoID ?? result.vid ?? uploadInfo.video_id;\n  if (!videoId) {\n    throw new CommandExecutionError(`提交抖音上传响应缺少 video id: ${JSON.stringify(payload).slice(0, 500)}`);\n  }\n  const meta = result.Meta ?? result.VideoMeta ?? {};\n  return {\n    video_id: videoId,\n    poster_uri: result.PosterUri ?? result.PosterURI ?? result.SnapshotUri ?? result.SnapshotURI ?? '',\n    width: Number(meta.Width ?? meta.width ?? 720) || 720,\n    height: Number(meta.Height ?? meta.height ?? 1280) || 1280,\n    raw: result,\n  };\n}\n","sourceCodeStart":184,"sourceCodeEnd":213,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/douyin/_shared/vod-upload.js#L184-L213","documentation":"Thrown by commitVideoUploadInner when the CommitUploadInner response is HTTP-ok with no error, but no video id can be extracted from Result.Results[0] (Vid/VideoId/VideoID/vid) or uploadInfo.video_id. It means the commit succeeded per the API but the library cannot determine the resulting video id. Thrown to prevent downstream code from publishing an undefined video id.","triggerScenarios":"Douyin changes the commit response shape so none of Vid/VideoId/VideoID/vid are present; a malformed but 200-status payload; passing an uploadInfo object whose video_id was also missing; a space where media processing returns results asynchronously with empty Results.","commonSituations":"Douyin API version drift after a backend update; testing against a new/empty VOD space returning unexpected result wrappers; manually constructed uploadInfo objects missing video_id.","solutions":["Log the truncated payload from the error message and check which field actually carries the video id","Add the new field name to the fallback chain at vod-upload.js:200","Ensure uploadInfo.video_id is set from the earlier ApplyUploadInner response","Re-run upload/commit; if persistent, pin to a known-good API Version param"],"exampleFix":"// before\nconst videoId = result.Vid ?? result.VideoId ?? result.VideoID ?? result.vid ?? uploadInfo.video_id;\n// after\nconst videoId = result.Vid ?? result.VideoId ?? result.VideoID ?? result.vid ?? result.VideoMeta?.Vid ?? uploadInfo?.video_id;\nif (!videoId) throw new Error('video id still missing: ' + JSON.stringify(result));","handlingStrategy":"type-guard","validationCode":"if (!uploadInfo?.video_id) throw new Error('uploadInfo.video_id missing from ApplyUpload step');","typeGuard":"function extractVideoId(result, uploadInfo) {\n  const id = result?.Vid ?? result?.VideoId ?? result?.VideoID ?? result?.vid ?? uploadInfo?.video_id;\n  return typeof id === 'string' && id.length > 0 ? id : null;\n}","tryCatchPattern":"try {\n  const out = await commitVideoUploadInner(info, creds);\n} catch (e) {\n  if (/缺少 video id/.test(e.message)) {\n    // persist raw payload and inspect field naming drift\n  } else throw e;\n}","preventionTips":["Always set uploadInfo.video_id from ApplyUploadInner output before committing","Pin/test against the current VOD API Version and watch for response-shape changelogs","Persist raw responses during integration so shape drift is debuggable","Fail fast in CI when video id extraction returns null"],"tags":["douyin","vod","upload","schema-change"],"backgroundTag":"response-missing-required-field","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}