{"record":{"id":"0960cc2bb1ad50bc","repo":"can1357/oh-my-pi","slug":"invalid-omp-profile-profile-profile-names-mu","errorCode":null,"errorMessage":"Invalid OMP profile \"${profile}\". Profile names must match ${PROFILE_NAME_RE.source}, cannot be \".\" or \"..\", cannot end with \".\", and cannot be a Windows reserved device name (CON, PRN, AUX, NUL, COM0-9, LPT0-9, or any of those with an extension).","messagePattern":"Invalid OMP profile \"(.+?)\"\\. Profile names must match (.+?), cannot be \"\\.\" or \"\\.\\.\", cannot end with \"\\.\", and cannot be a Windows reserved device name \\(CON, PRN, AUX, NUL, COM0-9, LPT0-9, or any of those with an extension\\)\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/utils/src/dirs.ts","lineNumber":69,"sourceCode":"/**\n * Normalize and validate a profile name. Returns `undefined` for the implicit\n * default (empty string, whitespace, or the explicit \"default\" sentinel) and\n * throws for syntactically invalid or platform-reserved names.\n *\n * Exported so consumers of `@oh-my-pi/pi-utils/dirs` (CLI bootstrap, tests,\n * downstream tools) can validate user input without re-deriving the rules.\n */\nexport function normalizeProfileName(profile: string | undefined): string | undefined {\n\tconst normalized = profile?.trim();\n\tif (!normalized || normalized === \"default\") return undefined;\n\tif (\n\t\tnormalized === \".\" ||\n\t\tnormalized === \"..\" ||\n\t\tnormalized.endsWith(\".\") ||\n\t\t!PROFILE_NAME_RE.test(normalized) ||\n\t\tWINDOWS_RESERVED_BASENAME_RE.test(normalized)\n\t) {\n\t\tthrow new Error(\n\t\t\t`Invalid OMP profile \"${profile}\". Profile names must match ${PROFILE_NAME_RE.source}, ` +\n\t\t\t\t`cannot be \".\" or \"..\", cannot end with \".\", and cannot be a Windows reserved device name ` +\n\t\t\t\t`(CON, PRN, AUX, NUL, COM0-9, LPT0-9, or any of those with an extension).`,\n\t\t);\n\t}\n\treturn normalized;\n}\n\n/**\n * Resolve the active profile from the two profile env vars. `OMP_PROFILE` is the\n * canonical variable and takes precedence; `PI_PROFILE` is the legacy\n * compatibility fallback, consulted only when `OMP_PROFILE` is undefined. An\n * explicitly-empty `OMP_PROFILE` therefore selects the default profile rather\n * than silently inheriting `PI_PROFILE`. Delegates validation/normalization to\n * {@link normalizeProfileName} (which throws on a syntactically invalid value).\n */\nexport function resolveProfileEnv(omp: string | undefined, pi: string | undefined): string | undefined {\n\treturn normalizeProfileName(omp !== undefined ? omp : pi);","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/utils/src/dirs.ts#L51-L87","documentation":"normalizeProfileName (packages/utils/src/dirs.ts) validates OMP profile names before using them as directory components. It rejects names that fail PROFILE_NAME_RE, are \".\"/\"..\", end with \".\", or match Windows reserved device names, throwing with a message that spells out all rules.","triggerScenarios":"Setting OMP_PROFILE (or passing a profile to profile()/resolveProfileEnv()/next()/getProfileRootDir()) with a value containing illegal characters, path traversal (\"..\"), a trailing dot, or a reserved name like \"CON\" or \"COM1\".","commonSituations":"Env files exporting OMP_PROFILE with spaces or slashes, CI configs using profile names like \"default.\" or \"aux\", users attempting traversal-style profile values, Windows-reserved names chosen on any platform.","solutions":["Rename the profile to match the allowed pattern shown in the error (alphanumeric/dash style per PROFILE_NAME_RE).","Remove leading/trailing dots and path separators from the profile value.","Avoid Windows reserved device names (CON, PRN, AUX, NUL, COM0-9, LPT0-9) even with extensions.","Check where OMP_PROFILE is set (shell rc, CI secrets, .env) and fix the literal value."],"exampleFix":"// before\nOMP_PROFILE=\"my profile.\"\nome profile  # Invalid OMP profile\n// after\nOMP_PROFILE=\"my-profile\"\nome profile","handlingStrategy":"validation","validationCode":"const PROFILE_NAME_RE = /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/; // match repo rule\nconst RESERVED = /^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9])(\\..*)?$/i;\nif (!PROFILE_NAME_RE.test(profile) || profile === '.' || profile === '..' || profile.endsWith('.') || RESERVED.test(profile)) {\n  throw new Error(`Invalid OMP profile: ${profile}`);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const p = normalizeProfileName(profile);\n} catch (err) {\n  if (err.message.startsWith('Invalid OMP profile')) {\n    console.error(`${err.message}\\nFix OMP_PROFILE in your shell env or config.`);\n    process.exitCode = 2;\n    return;\n  }\n  throw err;\n}","preventionTips":["Use only letters, digits, dashes, and underscores in profile names.","Never set OMP_PROFILE from untrusted/interpolated input without sanitizing.","Avoid Windows reserved device names and trailing dots regardless of platform.","Validate OMP_PROFILE in CI before running omp commands."],"tags":["configuration","validation","profiles","naming"],"backgroundTag":"invalid-profile-name","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}