{"record":{"id":"eaff85417a6b0c6a","repo":"Yeachan-Heo/oh-my-codex","slug":"name-must-be-non-empty","errorCode":null,"errorMessage":"${name} must be non-empty","messagePattern":"(.+?) must be non-empty","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mcp/hermes-bridge.ts","lineNumber":141,"sourceCode":"function jsonResult<T extends Record<string, unknown>>(data: T): HermesBridgeResult<T> {\n  return { ok: true, data };\n}\n\nfunction failure<T extends Record<string, unknown> = Record<string, unknown>>(\n  code: HermesBridgeFailureCode,\n  error: string,\n): HermesBridgeResult<T> {\n  return { ok: false, code, error };\n}\n\nfunction normalizeString(value: unknown, name: string, options: { required?: boolean } = {}): string | undefined {\n  if (value == null) {\n    if (options.required) throw new Error(`${name} is required`);\n    return undefined;\n  }\n  if (typeof value !== \"string\") throw new Error(`${name} must be a string`);\n  const trimmed = value.trim();\n  if (!trimmed && options.required) throw new Error(`${name} must be non-empty`);\n  return trimmed || undefined;\n}\n\nfunction requireMutation(args: Record<string, unknown>): void {\n  if (args.allow_mutation !== true) {\n    throw new Error(\"mutating Hermes bridge tools require allow_mutation: true\");\n  }\n}\n\nfunction normalizePositiveInteger(value: unknown, fallback: number, max: number): number {\n  if (value == null) return fallback;\n  const parsed = typeof value === \"number\" ? value : Number.parseInt(String(value), 10);\n  if (!Number.isInteger(parsed) || parsed <= 0) return fallback;\n  return Math.min(parsed, max);\n}\n\nasync function readJsonFile<T>(path: string): Promise<T | null> {\n  try {","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/mcp/hermes-bridge.ts#L123-L159","documentation":"normalizeString throws 'X must be non-empty' when a required string argument is present and typed correctly but trims to an empty string (\"\" or whitespace-only). Required fields must carry actual content, not blank padding.","triggerScenarios":"Passing prompt: \"\" or cwd: \"   \" to a Hermes bridge tool that marks the field required.","commonSituations":"Template strings interpolating empty variables, whitespace from copy-paste, or placeholder logic that supplies \"\" instead of omitting the field.","solutions":["Provide a meaningful non-whitespace value","Trim and check inputs before sending: if (!v.trim()) fill a default","Debug which upstream variable produced the blank value"],"exampleFix":"// before\n{ prompt: \"   \" }\n// after\n{ prompt: \"please continue the task\" }","handlingStrategy":"validation","validationCode":"for (const [k,v] of Object.entries(args)) if (typeof v === 'string' && !v.trim()) delete args[k]; // then required checks catch real omissions","typeGuard":"function isNonBlank(v: unknown): v is string { return typeof v === 'string' && v.trim().length > 0; }","tryCatchPattern":null,"preventionTips":["Trim inputs and default early","Don't pass placeholder empty strings for optional fields","Log outgoing args when debugging MCP calls"],"tags":["mcp","hermes-bridge","validation","empty-string"],"backgroundTag":"empty-required-field","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}