{"record":{"id":"6e50b194450fd87f","repo":"jackwener/OpenCLI","slug":"invalid-label-raw","errorCode":null,"errorMessage":"Invalid ${label}: ${raw}","messagePattern":"Invalid (.+?): (.+?)","errorType":"exception","errorClass":"ConfigError","httpStatus":null,"severity":"error","filePath":"clis/_atlassian/shared.js","lineNumber":31,"sourceCode":"\nfunction firstEnv(names) {\n    for (const name of names) {\n        const value = process.env[name]?.trim();\n        if (value) return value;\n    }\n    return '';\n}\n\nfunction normalizeBaseUrl(value, label) {\n    const raw = String(value ?? '').trim();\n    if (!raw) {\n        throw new ConfigError(`Missing ${label}`, `Set ${label}, for example https://example.atlassian.net`);\n    }\n    let parsed;\n    try {\n        parsed = new URL(raw);\n    } catch {\n        throw new ConfigError(`Invalid ${label}: ${raw}`, 'Use an absolute http(s) URL.');\n    }\n    if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\n        throw new ConfigError(`Invalid ${label}: ${raw}`, 'Use an http(s) URL.');\n    }\n    parsed.hash = '';\n    parsed.search = '';\n    return parsed.toString().replace(/\\/+$/, '');\n}\n\nfunction parseDeployment(raw, baseUrl) {\n    const value = String(raw || 'auto').trim().toLowerCase();\n    if (!DEPLOYMENTS.has(value)) {\n        throw new ConfigError('Invalid ATLASSIAN_DEPLOYMENT', 'Expected one of: cloud, datacenter, auto.');\n    }\n    if (value !== 'auto') return value;\n    const host = new URL(baseUrl).hostname;\n    return host === 'atlassian.net' || host.endsWith('.atlassian.net') ? 'cloud' : 'datacenter';\n}","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/_atlassian/shared.js#L13-L49","documentation":"This ConfigError is thrown by normalizeBaseUrl() when the configured Atlassian base URL cannot be parsed by the URL constructor — it is not an absolute URL. Typically the value is missing the scheme (e.g. \"example.atlassian.net\" instead of \"https://example.atlassian.net\") or contains stray characters.","triggerScenarios":"Setting the Atlassian base URL to a bare hostname like \"example.atlassian.net\", a value with quotes/spaces/newlines embedded, or a relative path like \"/wiki\".","commonSituations":"Copy-pasting the site name without https://, shell quoting issues leaving literal quotes in the env var, or confusing the site hostname with the full URL in docs.","solutions":["Prefix the value with an explicit scheme: use https://example.atlassian.net, not example.atlassian.net","Trim whitespace/quotes: set the env var cleanly (export ATLASSIAN_SITE='https://example.atlassian.net')","Validate with `node -e \"new URL(process.env.ATLASSIAN_SITE)\"` before running the CLI"],"exampleFix":"// before\nexport ATLASSIAN_SITE=\"example.atlassian.net\"   // Invalid: not absolute\n// after\nexport ATLASSIAN_SITE=\"https://example.atlassian.net\"","handlingStrategy":"validation","validationCode":"function isAbsoluteHttpUrl(v) {\n  try { const u = new URL(String(v).trim()); return u.protocol === 'https:' || u.protocol === 'http:'; }\n  catch { return false; }\n}\nif (!isAbsoluteHttpUrl(process.env.ATLASSIAN_SITE)) throw new Error('ATLASSIAN_SITE must be an absolute http(s) URL');","typeGuard":"const isAbsoluteHttpUrl = (v) => {\n  try { const u = new URL(v); return u.protocol === 'http:' || u.protocol === 'https:'; } catch { return false; }\n};","tryCatchPattern":"try {\n  return await cli.call('jira.search', { jql });\n} catch (e) {\n  if (e instanceof ConfigError && /^Invalid /.test(e.message)) {\n    console.error('Base URL must be absolute, e.g. https://example.atlassian.net');\n  }\n  throw e;\n}","preventionTips":["Always include the https:// scheme in site config values","Strip surrounding quotes/whitespace when setting env vars in shell","Run `node -e \"new URL(process.env.ATLASSIAN_SITE)\"` as a startup sanity check"],"tags":["configuration","url-validation","atlassian","invalid-url"],"backgroundTag":"invalid-url-config","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}