{"record":{"id":"b120d051129f85c4","repo":"facebook/docusaurus","slug":"json-stringify-redirect-validation-error","errorCode":null,"errorMessage":"${JSON.stringify(redirect)} => Validation error: ${error.message}","messagePattern":"(.+?) => Validation error: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/docusaurus-plugin-client-redirects/src/redirectValidation.ts","lineNumber":24,"sourceCode":" */\n\nimport {Joi, PathnameSchema} from '@docusaurus/utils-validation';\nimport type {RedirectItem} from './types';\n\nconst RedirectSchema = Joi.object<RedirectItem>({\n  from: PathnameSchema.required(),\n  to: Joi.string().required(),\n});\n\nexport function validateRedirect(redirect: RedirectItem): void {\n  const {error} = RedirectSchema.validate(redirect, {\n    abortEarly: true,\n    convert: false,\n  });\n\n  if (error) {\n    // Tells the user which redirect is the problem!\n    throw new Error(\n      `${JSON.stringify(redirect)} => Validation error: ${error.message}`,\n    );\n  }\n}\n","sourceCodeStart":6,"sourceCodeEnd":29,"githubUrl":"https://github.com/facebook/docusaurus/blob/3f483e80e326cc646b54b83d564b3f0c4881b9a6/packages/docusaurus-plugin-client-redirects/src/redirectValidation.ts#L6-L29","documentation":"Thrown by validateRedirect when a redirect object fails Joi schema validation (the 'from' field must be a valid pathname and 'to' must be a string, both required). The error message embeds the offending redirect via JSON.stringify so you can identify which entry is malformed. It uses abortEarly:true, so only the first problem is reported.","triggerScenarios":"Calling validateRedirect with a redirect missing 'from' or 'to', having an empty pathname, or having 'from' fail PathnameSchema (e.g. empty string or non-string). Happens during build when the client-redirects plugin processes its 'redirects' option array.","commonSituations":"Typos in docusaurus.config.js redirects option (writing `form:` instead of `from:`, omitting `to:`), passing a redirect where `from` is an empty string, or copying example config that used a placeholder. Also from a redirects JSON file imported with wrong key names.","solutions":["Inspect the printed JSON in the message: it shows the exact object that failed.","Ensure each redirect has a non-empty 'from' (leading slash, valid URL path) and a string 'to'.","Validate your redirects array with RedirectSchema before passing to the plugin."],"exampleFix":"// before\nredirects: [{ from: '', to: '/docs/intro' }, { form: '/a', to: '/b' }]\n// after\nredirects: [{ from: '/old', to: '/docs/intro' }, { from: '/a', to: '/b' }]","handlingStrategy":"validation","validationCode":"import {RedirectSchema} from '@docusaurus/plugin-client-redirects';\n// or replicate: Joi.object({ from: Joi.string().required(), to: Joi.string().required() })\nconst {error} = RedirectSchema.validate(redirect);\nif (error) throw new Error(`Bad redirect ${JSON.stringify(redirect)}: ${error.message}`);","typeGuard":"const isRedirect = (r: unknown): r is {from: string; to: string} =>\n  typeof r === 'object' && r !== null &&\n  typeof (r as any).from === 'string' && (r as any).from.startsWith('/') &&\n  typeof (r as any).to === 'string' && (r as any).to.length > 0;","tryCatchPattern":null,"preventionTips":["Lint your docusaurus.config.js redirects array with the schema in CI.","Keep redirects in a dedicated JSON file and validate it before import."],"tags":["config","validation","redirects","joi"],"backgroundTag":null,"analyzedSha":"3f483e80e326cc646b54b83d564b3f0c4881b9a6","analyzedAt":"2026-08-12T13:25:04.382Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}