{"record":{"id":"aa524e8f1ffdc756","repo":"immich-app/immich","slug":"schema-validation-failed-errors-join","errorCode":null,"errorMessage":"Schema validation failed:\n  ${errors.join('\n  ')}","messagePattern":"Schema validation failed:\n  (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"server/src/utils/misc.ts","lineNumber":264,"sourceCode":"        }\n\n        if (isSchema(value) && value.type === 'number') {\n          if (value.format === 'float') {\n            errors.push(`Invalid number format: ${schemaName}.${key}=float (use double instead). `);\n          }\n\n          // verify it was meant to be a number (and not an integer)\n          if (!value.format) {\n            errors.push(\n              `${schemaName}.${key} is a number (not an integer) and requires a format (e.g .meta({ format: 'double' })). `,\n            );\n          }\n        }\n      }\n      schema.required?.sort();\n\n      if (errors.length > 0) {\n        throw new Error(`Schema validation failed:\\n  ${errors.join('\\n  ')}`);\n      }\n    }\n  }\n\n  for (const [key, value] of Object.entries(document.paths)) {\n    const newKey = key.replace('/api/', '/');\n    delete document.paths[key];\n    document.paths[newKey] = value;\n  }\n\n  for (const path of Object.values(document.paths)) {\n    const operations = {\n      get: path.get,\n      put: path.put,\n      post: path.post,\n      delete: path.delete,\n      options: path.options,\n      head: path.head,","sourceCodeStart":246,"sourceCodeEnd":282,"githubUrl":"https://github.com/immich-app/immich/blob/4c7b30c18b55e74224ad1a223a2058ea4a13cc1f/server/src/utils/misc.ts#L246-L282","documentation":"patchOpenAPI post-processes the generated OpenAPI document and validates every component schema's numeric properties. Any number-typed property must declare an explicit format (e.g. 'double') and must not use the disallowed 'float' format; violations are accumulated and thrown together as a single Error from the swagger document build in useSwagger. This enforces a project-wide convention that all OpenAPI numbers are explicitly formatted, which some client generators and strict validators require.","triggerScenarios":"A route's response/request schema (defined via a zod-to-openapi registry or .meta() declarations) contains a property whose generated OpenAPI schema has type:'number' with either format:'float' or no format at all; the error fires when useSwagger calls patchOpenAPI on the document at startup.","commonSituations":"Declaring z.number() without .meta({ format: 'double' }) in an OpenAPI registry schema; using float format out of habit from other ecosystems; upgrading the framework so previously tolerated number schemas are now checked; adding a new endpoint whose DTO uses plain numbers.","solutions":["Find the offending schema.property named in the error message (format 'SchemaName.propertyKey') and add .meta({ format: 'double' }) or an explicit format to its zod/number definition","Replace any format: 'float' with format: 'double' (float is explicitly rejected by this validator)","If the property should be an integer, change the zod schema from z.number() to z.number().int() so it generates type:'integer' instead of type:'number'","Re-run the server; patchOpenAPI throws on the first validation pass, so iterate until the error list is empty"],"exampleFix":"// before\nz.number().meta({ description: 'Score' })\n// or\nz.number()\n\n// after\nz.number().meta({ description: 'Score', format: 'double' })\n// or, for integers:\nz.number().int()","handlingStrategy":"validation","validationCode":"// Audit all registered schemas before server start:\nfor (const [name, schema] of Object.entries(registry.definitions)) {\n  for (const [key, prop] of Object.entries((schema as any).properties ?? {})) {\n    const target = prop.type === 'array' ? prop.items : prop;\n    if (target?.type === 'number') {\n      if (!target.format) throw new Error(`${name}.${key} needs .meta({ format: 'double' })`);\n      if (target.format === 'float') throw new Error(`${name}.${key}: use 'double' not 'float'`);\n    }\n  }\n}","typeGuard":"function isSchema(v: unknown): v is SchemaObject { return typeof v === 'object' && v !== null && 'type' in v; }","tryCatchPattern":"try {\n  useSwagger(app);\n} catch (err) {\n  if (err instanceof Error && err.message.startsWith('Schema validation failed:')) {\n    console.error('Fix these OpenAPI schemas (see each listed property):\\n' + err.message);\n    process.exit(1); // fail fast at startup, do not serve broken docs\n  }\n  throw err;\n}","preventionTips":["Always declare .meta({ format: 'double' }) on every z.number() used in an OpenAPI registry","Use z.number().int() for integer fields so they emit type:'integer' and skip the number-format check","Never use format:'float' in this codebase; it is explicitly rejected","Run the swagger doc generation in CI (not just at server start) so schema violations fail the build","Create shared zod schema helpers (e.g. doubleNumber()) that apply the format automatically"],"tags":["openapi","swagger","schema-validation","startup"],"backgroundTag":"schema-validation-failed","analyzedSha":"4c7b30c18b55e74224ad1a223a2058ea4a13cc1f","analyzedAt":"2026-09-07T09:44:17.793Z","contentChangedAt":"2026-09-07T09:44:17.793Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}