{"record":{"id":"cbed0a062b5c77f6","repo":"can1357/oh-my-pi","slug":"invalid-bank-name-name-use-alphanumeric-hyp","errorCode":null,"errorMessage":"Invalid bank name '${name}'. Use alphanumeric, hyphens, underscores only.","messagePattern":"Invalid bank name '(.+?)'\\. Use alphanumeric, hyphens, underscores only\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"packages/mnemopi/src/core/banks.ts","lineNumber":97,"sourceCode":"\tgetBankStats(name: string): BankStats {\n\t\tconst dbPath = this.getBankDbPath(name);\n\t\tconst present = existsSync(dbPath);\n\t\tconst size = present ? statSync(dbPath).size : 0;\n\t\treturn { name, exists: present, db_path: dbPath, dbSizeBytes: size, db_size_bytes: size };\n\t}\n\tprivate validateName(name: string): void {\n\t\tif (name.length === 0) throw new ValueError(\"Bank name cannot be empty\");\n\t\tif (name === \"default\") return;\n\t\tif (name.length > 64) throw new ValueError(`Bank name '${name}' exceeds 64 characters`);\n\t\tfor (let i = 0; i < name.length; i++) {\n\t\t\tconst code = name.charCodeAt(i);\n\t\t\tconst ok =\n\t\t\t\t(code >= 48 && code <= 57) ||\n\t\t\t\t(code >= 65 && code <= 90) ||\n\t\t\t\t(code >= 97 && code <= 122) ||\n\t\t\t\tcode === 45 ||\n\t\t\t\tcode === 95;\n\t\t\tif (!ok) throw new ValueError(`Invalid bank name '${name}'. Use alphanumeric, hyphens, underscores only.`);\n\t\t}\n\t}\n}\n\nlet defaultBank = \"default\";\n\nexport function createBank(name: string, dataDir?: string): string {\n\tconst manager = new BankManager(dataDir);\n\treturn manager.createBank(name);\n}\nexport function deleteBank(name: string, dataDir?: string, force = false): boolean {\n\tconst manager = new BankManager(dataDir);\n\treturn manager.deleteBank(name, force);\n}\nexport function listBanks(dataDir?: string): string[] {\n\tconst manager = new BankManager(dataDir);\n\treturn manager.listBanks();\n}","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/mnemopi/src/core/banks.ts#L79-L115","documentation":"Bank names may only contain ASCII alphanumerics, hyphens, and underscores (validated per character code in `validateName()`). Anything else — spaces, slashes, dots, Unicode — is rejected, again because names map directly to directory names.","triggerScenarios":"Calling any bank-taking API (`createBank`, `deleteBank`, `renameBank` old/new, `getBankDbPath`) with a name containing a forbidden character (e.g. `\"my bank\"`, `\"project/x\"`, `\"café\"`).","commonSituations":"Passing branch names with `/` or paths as bank names, names with spaces from UI input, non-ASCII names from localized tooling, shell interpolation introducing slashes.","solutions":["Sanitize the name: replace `[^^A-Za-z0-9_-]` with `-` before calling.","Document/limit the allowed charset at your app's input boundary.","Use a slugifier for derived names (branch/project titles).","Catch the ValueError and re-prompt or auto-fix the name."],"exampleFix":"// before\nbanks.createBank(\"feature/auth v2\");\n// after\nconst safe = name.replace(/[^A-Za-z0-9_-]/g, \"-\");\nbanks.createBank(safe); // \"feature-auth-v2\"","handlingStrategy":"validation","validationCode":"const BANK_NAME_RE = /^[A-Za-z0-9_-]+$/;\nif (name !== \"default\" && !BANK_NAME_RE.test(name)) {\n  throw new Error(`Invalid bank name: ${name}`);\n}","typeGuard":"null","tryCatchPattern":"try {\n  banks.createBank(name);\n} catch (err) {\n  if (err instanceof ValueError && err.message.includes(\"Invalid bank name\")) {\n    banks.createBank(name.replace(/[^A-Za-z0-9_-]/g, \"-\"));\n  } else throw err;\n}","preventionTips":["Sanitize all bank names with /^[A-Za-z0-9_-]+$/ filtering before any call.","Slugify branch/project-derived names.","Reject unsafe names at the input layer with a clear message.","Add a shared sanitizeBankName() utility instead of fixing per-callsite."],"tags":["bank","validation","invalid-characters","naming"],"backgroundTag":"invalid-argument","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}