jackwener/OpenCLI · error · CommandExecutionError

Pin ${pinId} was created but could not be moved into section

Error message

Pin ${pinId} was created but could not be moved into section ${sectionId}: ${err.message}

What it means

movePinToSection wraps PinResource/update, the only endpoint that actually honours board_section_id (create endpoints answer 200 but file the pin at board root). If that update request fails, the error is rethrown as CommandExecutionError noting the pin exists but sits on the board root, with a manual pin-update remediation command.

Source

Thrown at clis/pinterest/utils.js:350

  return { sectionId: String(match.id), title: (match.title || '').trim(), slug: match.slug || '' };
}

/**
 * Move an existing pin into a board section.
 * The create endpoints (PinResource/create, RepinResource/create) accept a section key, answer
 * HTTP 200, and file the pin at the board root anyway — only PinResource/update honours it. So
 * callers that create a pin have to follow up with this second request.
 */
export async function movePinToSection(page, pinId, boardId, sectionId, sourceUrl) {
  try {
    await pinterestResourceUpdate(
      page,
      'PinResource',
      { id: String(pinId), board_id: String(boardId), board_section_id: String(sectionId) },
      sourceUrl,
    );
  } catch (err) {
    throw new CommandExecutionError(
      `Pin ${pinId} was created but could not be moved into section ${sectionId}: ${err.message}`,
      `The pin is on the board root — move it with \`opencli pinterest pin-update ${pinId} --board <board> --section ${sectionId}\``,
    );
  }
}

/** Page a feed via bookmark until `limit` rows; mapItem returns a row or null to skip. */
export async function collectResults(
  page,
  { resource, baseOptions, sourceUrl, limit, keyField, mapItem, pageSize = 25, maxPages = 12 },
) {
  const rows = [];
  const seen = new Set();
  let bookmark = null;

  for (let pageIndex = 0; pageIndex < maxPages && rows.length < limit; pageIndex++) {
    const options = { ...baseOptions, page_size: pageSize };
    if (bookmark) options.bookmarks = [bookmark];

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Move the pin manually with `opencli pinterest pin-update <pinId> --board <board> --section <sectionId>` as the error suggests.
  2. Re-authenticate (refresh the Pinterest session) and retry the move.
  3. Retry after a short delay — the pin may not have been immediately updatable after creation.
  4. Verify the section still exists with `board-sections <board>` before retrying.

Example fix

// pin left at board root after failed move
opencli pinterest pin-update 9876543210 --board someuser/recipes --section desserts
Defensive patterns

Strategy: try-catch

Validate before calling

const sections = await listBoardSections(board);
if (!sections.some(s => String(s.id) === String(sectionId))) {
  throw new Error(`Section ${sectionId} no longer exists — aborting before pin create`);
}

Try / catch

try {
  await movePinToSection(page, pinId, boardId, sectionId);
} catch (err) {
  if (String(err.message).includes('could not be moved into section')) {
    await delay(2000);
    await runCmd(['opencli', 'pinterest', 'pin-update', pinId, '--board', board, '--section', sectionId]);
  } else throw err;
}

Prevention

When it happens

Trigger: PinResource/update (id, board_id, board_section_id) throws — network failure, stale/insufficient Pinterest session, section deleted between create and move, or Pinterest API rejecting the update — immediately after a pin was successfully created.

Common situations: Session cookie expired mid-script; a race where the section is removed concurrently; Pinterest rate-limiting or flaking on the second write; replication lag where the just-created pin isn't yet updatable.

Related errors


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