{"record":{"id":"068badbee170b383","repo":"ruvnet/ruflo","slug":"validation-failed-result-error","errorCode":null,"errorMessage":"Validation failed: ${result.error}","messagePattern":"Validation failed: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"v3/@claude-flow/cli-core/src/mcp-tools/validate-input.ts","lineNumber":201,"sourceCode":"      return { valid: false, sanitized: {}, error: `${label}[\"${name}\"] must be a string` };\n    }\n    if (rawVal.length > 32_768) {\n      return { valid: false, sanitized: {}, error: `${label}[\"${name}\"] exceeds 32768 characters` };\n    }\n    if (rawVal.includes('\\0')) {\n      return { valid: false, sanitized: {}, error: `${label}[\"${name}\"] contains a null byte` };\n    }\n    out[name] = rawVal;\n  }\n  return { valid: true, sanitized: out };\n}\n\n/**\n * Assert validation or throw with a structured error.\n */\nexport function assertValid(result: ValidationResult): string {\n  if (!result.valid) {\n    throw new Error(`Validation failed: ${result.error}`);\n  }\n  return result.sanitized;\n}\n\n// Try to load the full @claude-flow/security module for enhanced validation\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nlet _securityModule: Record<string, any> | null = null;\nlet _securityLoaded = false;\n\nasync function getSecurityModule(): Promise<Record<string, any> | null> {\n  if (_securityLoaded) return _securityModule;\n  _securityLoaded = true;\n  try {\n    // Dynamic import — @claude-flow/security is an optional dependency\n    _securityModule = await (Function('return import(\"@claude-flow/security\")')() as Promise<Record<string, any>>);\n  } catch {\n    // @claude-flow/security is optional — fallback to inline validation above\n  }","sourceCodeStart":183,"sourceCodeEnd":219,"githubUrl":"https://github.com/ruvnet/ruflo/blob/6b01dc5a687b26b3e218f796de45ec51f8fa9e8c/v3/@claude-flow/cli-core/src/mcp-tools/validate-input.ts#L183-L219","documentation":"Thrown by assertValid when a ValidationResult has valid=false. assertValid is the fail-fast bridge over the input-sanitization layer: it propagates the specific sub-error string (e.g. a null byte in a field, a disallowed value) via the interpolated message. It exists to turn soft validation failures into hard exceptions at trust boundaries.","triggerScenarios":"Calling assertValid(result) where result came from a validate* function that detected unsafe input — a property containing a null byte, a value failing schema/type rules, or an unknown/extra field under strict mode. The message carries result.error verbatim, so the root cause is in the original validation result.","commonSituations":"Processing untrusted MCP/tool input that contains control characters (null bytes, odd unicode), client payloads with missing required fields, or version skew where a newer client sends fields the validator rejects. Common at the entry point of MCP tools that call assertValid immediately after validateInput.","solutions":["Inspect the full interpolated message — the suffix after 'Validation failed:' is the precise field and reason (e.g. label[\"name\"] contains a null byte).","Fix the input at the source: strip/normalize control characters or supply the missing required field before re-validating.","If running a server, return a 400 with result.error to the client rather than letting assertValid throw an unhandled exception.","Run validateInput separately and branch on result.valid so you can collect all field errors instead of failing on the first one."],"exampleFix":"// before\nconst sanitized = assertValid(validateInput(params));\n\n// after\nconst result = validateInput(params);\nif (!result.valid) {\n  return { status: 400, error: result.error };\n}\nconst sanitized = result.sanitized;","handlingStrategy":"validation","validationCode":"const result = validateInput(params);\nif (!result.valid) {\n  return { status: 400, error: result.error };\n}\n// only now is it safe to assertValid / use sanitized\nconst sanitized = result.sanitized;","typeGuard":"function isValidationOk(r: ValidationResult): r is { valid: true; sanitized: Record<string, unknown> } {\n  return r.valid === true;\n}","tryCatchPattern":"try {\n  assertValid(result);\n} catch (e) {\n  // e.message === `Validation failed: ${result.error}`\n  return { status: 400, error: (e as Error).message };\n}","preventionTips":["Run validateInput and branch on result.valid rather than always asserting.","Sanitize untrusted input (strip null bytes) before validation if clients are noisy.","Return result.error to clients as a 400 instead of letting it throw.","Keep validator schemas in lockstep with the client payload version."],"tags":["validation","security","input-sanitization","mcp-tools"],"backgroundTag":null,"analyzedSha":"6b01dc5a687b26b3e218f796de45ec51f8fa9e8c","analyzedAt":"2026-08-12T13:20:50.148Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}