{"record":{"id":"c578793fa827e3f1","repo":"jackwener/OpenCLI","slug":"invalid-jira-issue-key-key","errorCode":null,"errorMessage":"Invalid Jira issue key: ${key}","messagePattern":"Invalid Jira issue key: (.+?)","errorType":"validation","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"clis/jira/shared.js","lineNumber":104,"sourceCode":"    if (selection?.mode === 'selected') {\n        return [...new Set([...selection.ids, ...extraFields.filter(Boolean)])].join(',');\n    }\n    const configured = Object.values(configuredFieldNames()).filter(Boolean);\n    return [...new Set([...DEFAULT_ISSUE_FIELDS, ...configured, ...extraFields.filter(Boolean)])].join(',');\n}\n\nexport function issueSelectionIncludes(selection, field) {\n    return selection === null || selection?.mode === 'auto' || selection?.ids?.includes(field) === true;\n}\n\nexport function parseJiraLimit(value, fallback = 20, max = 100) {\n    return parseLimit(value, fallback, max, 'jira limit');\n}\n\nexport function requireIssueKey(value) {\n    const key = requireString(value, 'Jira issue key');\n    if (!/^[A-Za-z][A-Za-z0-9_]+-\\d+$/.test(key)) {\n        throw new ArgumentError(`Invalid Jira issue key: ${key}`, 'Expected a key like PROJECT-123.');\n    }\n    return key.toUpperCase();\n}\n\nfunction displayUser(user) {\n    if (!user || typeof user !== 'object') return '';\n    return String(user.displayName ?? user.name ?? user.emailAddress ?? user.accountId ?? '');\n}\n\nfunction valueName(value) {\n    if (!value) return '';\n    if (typeof value === 'string') return value;\n    if (typeof value === 'object') return String(value.name ?? value.value ?? value.key ?? value.id ?? '');\n    return String(value);\n}\n\nfunction valueNames(values) {\n    return Array.isArray(values) ? values.map(valueName).filter(Boolean) : [];","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/jira/shared.js#L86-L122","documentation":"ArgumentError from `requireIssueKey` in clis/jira/shared.js:104, raised when the issue key fails the pattern /^[A-Za-z][A-Za-z0-9_]+-\\d+$/: a project key (letters/digits/underscore, starting with a letter), a hyphen, then a numeric id. The key is validated client-side and uppercased on success.","triggerScenarios":"Passing a bare number (12345), a URL (https://jira.example.com/browse/PROJ-1), a lowercase-but-valid key is fine but things like PROJ-1a, -PROJ-1, PROJ 1, PROJ–1 (en dash) all fail, or an empty value.","commonSituations":"Pasting the full issue URL or a Jira ticket title instead of the key; smart-quote/en-dash corruption from copy-paste; scripts passing internal numeric ids.","solutions":["Use the canonical key form: PROJ-123 (letters/digits/underscore project code, hyphen, number).","Extract the key from a URL: the segment after /browse/.","Replace smart dashes: change – or — to a plain hyphen -.","If you only have a numeric id, resolve it via the Jira API or use the id directly with the appropriate API resource."],"exampleFix":"// before\nkey: 'https://jira.example.com/browse/proj-1'\n// after\nkey: 'PROJ-1'  // extracted key; input is uppercased by requireIssueKey","handlingStrategy":"validation","validationCode":"const ISSUE_KEY_RE = /^[A-Za-z][A-Za-z0-9_]+-\\d+$/;\nfunction toIssueKey(input) {\n  // Accept a URL and extract the key\n  const fromUrl = input.match(/\\/browse\\/([A-Za-z][A-Za-z0-9_]+-\\d+)/);\n  const key = (fromUrl ? fromUrl[1] : input).replace(/[\\u2010-\\u2015\\u2212]/g, '-').trim();\n  if (!ISSUE_KEY_RE.test(key)) throw new Error(`Expected a key like PROJECT-123, got: ${input}`);\n  return key.toUpperCase();\n}","typeGuard":"const isIssueKey = (v) => typeof v === 'string' && /^[A-Za-z][A-Za-z0-9_]+-\\d+$/.test(v.trim());","tryCatchPattern":"import { ArgumentError } from '@jackwener/opencli/errors';\ntry {\n  await run(['jira', 'issue', key]);\n} catch (e) {\n  if (e instanceof ArgumentError && e.message.startsWith('Invalid Jira issue key')) {\n    console.error('Use PROJECT-123 form, not a URL or bare numeric id.');\n  } else throw e;\n}","preventionTips":["Normalize inputs: extract /browse/<KEY> from pasted URLs.","Replace smart dashes with plain hyphens after copy-paste.","Uppercase project keys before passing (validating anyway).","Never pass internal numeric issue ids where a key is required."],"tags":["argument-validation","jira","cli","parsing"],"backgroundTag":"invalid-argument-value","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}