{"record":{"id":"b11fb518453b14fc","repo":"jackwener/OpenCLI","slug":"board-trimmed-returned-an-unusable-url-url","errorCode":null,"errorMessage":"Board ${trimmed} returned an unusable url: ${url}","messagePattern":"Board (.+?) returned an unusable url: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/pinterest/utils.js","lineNumber":307,"sourceCode":"      `Not a board reference: \"${trimmed}\"`,\n      'Expected <username>/<slug>, a board URL, or a numeric board id (from `board-pins`/`user-boards`)',\n    );\n  }\n\n  await page.goto(`${PINTEREST_BASE}/`);\n  const { data: board } = await pinterestResourceFetch(\n    page,\n    'BoardResource',\n    { board_id: trimmed, field_set_key: 'detailed' },\n    '/',\n  );\n  const url = board && board.url;\n  if (!url) {\n    throw new ArgumentError(`No board with id \"${trimmed}\"`, 'Check the id with `opencli pinterest user-boards <username>`');\n  }\n  const parts = decodeSegment(url).split('/').filter(Boolean);\n  if (parts.length < 2) {\n    throw new CommandExecutionError(`Board ${trimmed} returned an unusable url: ${url}`);\n  }\n  // Hand the fetched board back so callers do not re-request what we already have.\n  return { username: parts[0], slug: parts[1], path: `/${parts[0]}/${parts[1]}/`, board };\n}\n\n/**\n * Resolve a --section value against the board's real sections, accepting an id or a slug.\n * Pinterest ignores an unknown section silently, so an unmatched value must fail here.\n * Returns { sectionId, title, slug }.\n */\nexport async function resolveSection(page, boardId, sectionValue, sourceUrl) {\n  const wanted = String(sectionValue ?? '').trim();\n  const { results } = await pinterestResourceFetch(page, 'BoardSectionsResource', { board_id: String(boardId) }, sourceUrl);\n  const sections = results.filter((section) => section && section.id);\n  if (sections.length === 0) {\n    throw new ArgumentError(`Board has no sections, so --section \"${wanted}\" cannot be used`, 'Create one first with `opencli pinterest board-section-create`');\n  }\n  const folded = normalizeForMatch(wanted);","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/pinterest/utils.js#L289-L325","documentation":"After BoardResource returns a board, resolveBoardTarget splits the board's `url` field into username/slug segments. If the decoded url yields fewer than 2 path segments (e.g. empty, '/' or a malformed value), it throws this CommandExecutionError because the code cannot derive a `<username>/<slug>` path from it.","triggerScenarios":"BoardResource returns a board object whose `url` field is missing segments, empty, or in an unexpected format — e.g. truncated API response, Pinterest schema change, or a server-side stub/placeholder board object.","commonSituations":"Pinterest API schema drift (url field renamed or shaped differently); rate-limited/partial responses returning a minimal board object; a proxy or test fixture returning a fake board payload with url:'/'.","solutions":["Retry the command — a transient/partial API response may resolve correctly next time.","Pass the board as `<username>/<slug>` or a full board URL so no BoardResource url-parsing is needed.","Print the raw board payload (verbose/debug mode) and inspect the `url` field to confirm the schema.","Update the CLI if Pinterest changed the BoardResource response shape."],"exampleFix":"// before\n--board 5123456789012345   # BoardResource returned url: '/'\n// after\n--board someuser/recipe-ideas","handlingStrategy":"fallback","validationCode":null,"typeGuard":"function hasUsableBoardUrl(board) {\n  return !!board && typeof board.url === 'string'\n    && board.url.split('/').filter(Boolean).length >= 2;\n}","tryCatchPattern":"try {\n  await runCmd(['--board', numericId]);\n} catch (err) {\n  if (String(err.message).includes('returned an unusable url')) {\n    // fall back to explicit username/slug reference\n    await runCmd(['--board', `${username}/${slug}`]);\n  } else throw err;\n}","preventionTips":["Use `<username>/<slug>` or full board URLs, which bypass BoardResource url parsing entirely.","Retry once on this error — partial/transient API payloads often resolve on a second call.","Log raw BoardResource payloads in verbose mode to detect schema drift early."],"tags":["pinterest","api-schema","parsing","board"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}