jackwener/OpenCLI · error · CommandExecutionError

twitter_collection_unresolved_relationship

twitter_collection_unresolved_relationship

Error message

twitter_collection_unresolved_relationship: repost target is unavailable

What it means

When a collected timeline post is a repost, extractRelationship requires the resolved repost target (retweeted_status_result.result) and a concrete post_id. If only an ID stub exists without resolvable content, or the target can't be resolved to a post_id, the library throws rather than emitting a repost entry with an unusable target.

Source

Thrown at clis/twitter/collection.js:126

        : contextStatus;
    return {
        post_id: postId,
        author_handle: authorHandle,
        author_id: authorId,
        url: postId && authorHandle ? `https://x.com/${authorHandle}/status/${postId}` : null,
        context_status: resolvedContextStatus,
    };
}

function extractRelationship(result) {
    const tweet = unwrapTweetResult(result);
    const legacy = tweet?.legacy || {};
    const repostResult = tweet?.retweeted_status_result?.result || legacy.retweeted_status_result?.result || null;
    const repostId = legacy.retweeted_status_id_str || null;
    if (repostResult || repostId) {
        const target = relationshipTarget(repostResult, repostId, repostResult ? 'complete' : 'unknown');
        if (!repostResult || !target.post_id) {
            throw new CommandExecutionError('twitter_collection_unresolved_relationship: repost target is unavailable');
        }
        return { kind: 'repost', target };
    }
    const quoteResult = tweet?.quoted_status_result?.result || legacy.quoted_status_result?.result || null;
    const quoteId = legacy.quoted_status_id_str || null;
    if (legacy.is_quote_status || quoteResult || quoteId) {
        return {
            kind: 'quote',
            target: relationshipTarget(quoteResult, quoteId, quoteResult ? 'complete' : 'unavailable'),
        };
    }
    const replyId = legacy.in_reply_to_status_id_str || null;
    const replyHandle = normalizeTwitterScreenName(legacy.in_reply_to_screen_name || '') || null;
    const replyAuthorId = typeof legacy.in_reply_to_user_id_str === 'string' && legacy.in_reply_to_user_id_str.trim()
        ? legacy.in_reply_to_user_id_str
        : null;
    if (replyId || replyHandle || replyAuthorId) {
        return {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run collection — tombstones are sometimes transient; retry after a delay
  2. Skip or log-and-continue for that tweet if your tooling allows (the error is per-post)
  3. Check whether the target tweet is deleted/withheld by fetching its ID directly
  4. Update the CLI — newer X API shapes may need a newer unwrap path

Example fix

null
Defensive patterns

Strategy: try-catch

Validate before calling

function repostTargetAvailable(tweet) {
  const legacy = tweet?.legacy || {};
  const result = tweet?.retweeted_status_result?.result || legacy.retweeted_status_result?.result;
  const id = legacy.retweeted_status_id_str;
  return Boolean(result && result?.rest_id) || Boolean(!result && id); // stub-only still fails downstream
}

Type guard

function hasResolvableRepost(tweet) {
  const r = tweet?.retweeted_status_result?.result ?? tweet?.legacy?.retweeted_status_result?.result;
  return r != null && typeof r.rest_id === 'string';
}

Try / catch

try {
  posts.push(extractCollectionPost(entry, seen));
} catch (err) {
  if (String(err.message).startsWith('twitter_collection_unresolved_relationship')) {
    console.warn('skipping post with unavailable repost target');
  } else throw err;
}

Prevention

When it happens

Trigger: A tweet has legacy.retweeted_status_id_str or a retweeted_status_result but the embedded result is missing/tombstoned (deleted or withheld repost target), so target.post_id cannot be built.

Common situations: Archiving timelines where the reposted tweet was deleted or made unavailable after the repost; withheld/geo-blocked content returning tombstone results; X GraphQL payloads omitting retweeted_status_result for older reposts.

Related errors


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