jackwener/OpenCLI · error · CommandExecutionError

抖音上传授权缺少 AccessKeyID/SecretAccessKey/SessionToken

Error message

抖音上传授权缺少 AccessKeyID/SecretAccessKey/SessionToken

What it means

The parsed auth JSON exists but is missing at least one of AccessKeyID, SecretAccessKey, or SessionToken — the trio required to sign AWS4 requests against the VOD upload API. The library refuses to continue with incomplete STS credentials since every subsequent signed call would fail.

Source

Thrown at clis/douyin/_shared/vod-upload.js:119

  }
  if (result.status_code !== 0) {
    const message = result.status_msg ?? result.message ?? 'unknown error';
    if (result.status_code === 401 || result.status_code === 403 || /login|cookie|auth|captcha|verify|forbidden|permission|登录|登陆|权限|验证|验证码/i.test(String(message))) {
      throw new AuthRequiredError('creator.douyin.com', `获取抖音上传授权失败: ${message}`);
    }
    throw new CommandExecutionError(`获取抖音上传授权失败: ${JSON.stringify(result)}`);
  }
  if (!result.auth) {
    throw new CommandExecutionError(`获取抖音上传授权失败: ${JSON.stringify(result)}`);
  }
  let auth;
  try {
    auth = JSON.parse(result.auth);
  } catch (error) {
    throw new CommandExecutionError(`解析抖音上传授权失败: ${error instanceof Error ? error.message : String(error)}`);
  }
  if (!auth.AccessKeyID || !auth.SecretAccessKey || !auth.SessionToken) {
    throw new CommandExecutionError('抖音上传授权缺少 AccessKeyID/SecretAccessKey/SessionToken');
  }
  return {
    access_key_id: auth.AccessKeyID,
    secret_access_key: auth.SecretAccessKey,
    session_token: auth.SessionToken,
    user_id: extractUserIdFromSessionToken(auth.SessionToken),
    expired_time: auth.ExpiredTime,
    current_time: auth.CurrentTime,
  };
}

export async function applyVideoUploadInner(fileSize, credentials) {
  const params = new URLSearchParams({
    Action: 'ApplyUploadInner',
    Version: '2020-11-19',
    SpaceName: VOD_SPACE_NAME,
    FileType: 'video',
    IsInner: '1',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log the parsed auth object to see exactly which keys are present and how they are cased.
  2. Accept alternate casings in code (AccessKeyId/AccessKeyID, SessionToken/sessionToken) if Douyin changed field names.
  3. Re-login and retry — a restricted or expired session can yield partial credentials.
  4. Confirm the account can still get STS tokens for the VOD space (no admin-imposed restriction).
  5. Update the CLI if a Douyin API version change renamed the credential fields.

Example fix

// before
if (!auth.AccessKeyID || !auth.SecretAccessKey || !auth.SessionToken) {
  throw new CommandExecutionError('抖音上传授权缺少 AccessKeyID/SecretAccessKey/SessionToken');
}
// after
const accessKey = auth.AccessKeyID ?? auth.AccessKeyId;
const secretKey = auth.SecretAccessKey ?? auth.SecretAccessKeyId;
const token = auth.SessionToken ?? auth.sessionToken;
if (!accessKey || !secretKey || !token) {
  throw new CommandExecutionError('抖音上传授权缺少 AccessKeyID/SecretAccessKey/SessionToken');
}
Defensive patterns

Strategy: validation

Validate before calling

function hasCompleteStsCredentials(auth) {
  return Boolean(auth && (auth.AccessKeyID || auth.AccessKeyId)
    && (auth.SecretAccessKey || auth.SecretAccessKeyId)
    && (auth.SessionToken || auth.sessionToken));
}
// before signing requests:
if (!hasCompleteStsCredentials(auth)) throw new Error('STS 凭证不完整');

Type guard

null

Try / catch

try {
  const creds = await getUploadAuthV5Credentials(page);
} catch (e) {
  if (/缺少 AccessKeyID/.test(e.message)) {
    console.error('收到的 auth 键:', Object.keys(lastAuthJson)); // inspect and adapt
  }
  throw e;
}

Prevention

When it happens

Trigger: auth parses to an object lacking one or more of AccessKeyID/SecretAccessKey/SessionToken — e.g. Douyin returned an error-shaped or partially-populated credential object, or the field names changed (camelCase vs PascalCase).

Common situations: Douyin API field-name drift (e.g. AccessKeyId vs AccessKeyID); account restricted from STS issuance so only some fields returned; upstream schema change after an app update; clock/region issues returning a degraded payload.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/65c739d8db79670c. Report an issue: GitHub.