jackwener/OpenCLI · error · CommandExecutionError

发布成功但未返回 aweme_id/item_id: ${JSON.stringify(publishRes)}

Error message

发布成功但未返回 aweme_id/item_id: ${JSON.stringify(publishRes)}

What it means

After submitting the scheduled publish via create_v2 (browserFetch POST to publishUrl), the command expects the response to carry aweme_id or item_id to build the video URL. If neither field is present, it throws this CommandExecutionError with the full JSON response — meaning the request likely failed or returned an error envelope despite HTTP success.

Source

Thrown at clis/douyin/publish.js:326

                },
                anchor: {},
                sync: {
                    should_sync: false,
                    sync_to_toutiao: kwargs.sync_toutiao ? 1 : 0,
                },
                open_platform: {},
                assistant: { is_preview: 0, is_post_assistant: 1 },
                declare: { user_declare_info: '{}' },
            },
        };
        const publishUrl = `https://creator.douyin.com/web/api/media/aweme/create_v2/?read_aid=2906&${DEVICE_PARAMS}`;
        process.stderr.write('  创建定时发布...\n');
        const publishRes = (await browserFetch(page, 'POST', publishUrl, {
            body: publishBody,
        }));
        const awemeId = publishRes.aweme_id ?? publishRes.item_id;
        if (!awemeId) {
            throw new CommandExecutionError(`发布成功但未返回 aweme_id/item_id: ${JSON.stringify(publishRes)}`);
        }
        const url = `https://www.douyin.com/video/${awemeId}`;
        const publishTimeStr = new Date(timingTs * 1000).toLocaleString('zh-CN', {
            timeZone: 'Asia/Tokyo',
        });
        return [
            {
                status: '✅ 定时发布成功!',
                aweme_id: awemeId,
                url,
                publish_time: publishTimeStr,
            },
        ];
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect the JSON in the error message — usually a status_code/message explaining the real failure
  2. Refresh the Douyin login session in the automation browser and retry
  3. Check for rate limiting or account risk-control notices on the account
  4. If the response shape changed, update the aweme_id/item_id extraction in publish.js

Example fix

// before
const awemeId = publishRes.aweme_id ?? publishRes.item_id;
// after (diagnose first)
if (publishRes.status_code && publishRes.status_code !== 0) {
  throw new Error(`create_v2 failed: ${publishRes.status_code} ${publishRes.message}`);
}
const awemeId = publishRes.aweme_id ?? publishRes.item_id ?? publishRes.data?.aweme_id;
Defensive patterns

Strategy: try-catch

Validate before calling

// Probe session validity before publishing
const me = await fetchDouyinApi(page, '/aweme/v1/user/profile/self/');
if (!me?.data?.user) throw new Error('Douyin session expired; re-login before publish');

Type guard

function hasPublishId(res) {
  return typeof res?.aweme_id === 'string' || typeof res?.item_id === 'string';
}

Try / catch

try {
  const url = await douyin.publish({ title, caption });
} catch (e) {
  if (e instanceof CommandExecutionError && /aweme_id\/item_id/.test(e.message)) {
    const body = JSON.parse(e.message.match(/\{[\s\S]*\}/)?.[0] ?? '{}');
    console.error('create_v2 said:', body.status_code, body.message); // real cause
    // refresh session / handle rate limit, then retry
  } else throw e;
}

Prevention

When it happens

Trigger: publishRes lacks both aweme_id and item_id — e.g., Douyin returned { status_code: <nonzero>, message: ... } or a login/permission redirect body instead of a created-video object.

Common situations: Session/cookie expiry so create_v2 silently returns an error body; rate limiting or risk control on the account; content rejected at submit time with an error payload; API contract change renaming the id field.

Related errors


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