{"record":{"id":"eafdb4ada01dea6b","repo":"badges/shields","slug":"prettyerrormessage","errorCode":null,"errorMessage":"${prettyErrorMessage}","messagePattern":"\\$\\{prettyErrorMessage\\}","errorType":"validation","errorClass":"ErrorClass","httpStatus":null,"severity":"error","filePath":"core/base-service/validate.js","lineNumber":38,"sourceCode":"\n  const { error, value } = schema.validate(data, options)\n  if (error) {\n    trace.logTrace(\n      'validate',\n      emojic.womanShrugging,\n      traceErrorMessage,\n      error.message,\n    )\n\n    let prettyMessage = prettyErrorMessage\n    if (includeKeys) {\n      const keys = error.details.map(({ path }) => path)\n      if (keys) {\n        prettyMessage = `${prettyErrorMessage}: ${keys.join(', ')}`\n      }\n    }\n\n    throw new ErrorClass({ prettyMessage, underlyingError: error })\n  } else {\n    trace.logTrace('validate', emojic.bathtub, traceSuccessMessage, value, {\n      deep: true,\n    })\n    return value\n  }\n}\n\nexport default validate\n","sourceCodeStart":20,"sourceCodeEnd":48,"githubUrl":"https://github.com/badges/shields/blob/766fd8bc89a90b8534dc573ab72dec30215ab1ec/core/base-service/validate.js#L20-L48","documentation":"validate() runs a Joi schema over upstream/service data with abortEarly:false, and on failure throws the configured ErrorClass (typically InvalidResponse) with the prettyMessage. Its message defaults to prettyErrorMessage ('data does not match schema'); when includeKeys is set it appends the failing schema paths. This signals that the upstream data did not conform to the expected structure.","triggerScenarios":"schema.validate(data) returns an error — any service or result whose upstream JSON is missing required fields, has wrong types (string where number), or violates a Joi rule (e.g. regex on version strings).","commonSituations":"Upstream API changed its response shape after a version bump, optional fields absent for some repos, date/number format differences across provider instances, self-hosted provider with older/newer schema.","solutions":["Read the prettyMessage/underlyingError to see which schema paths failed (enable includeKeys).","Fetch the raw upstream response and compare it against the service's Joi schema.","Update the schema (or the service) for upstream API changes and file/PR the fix.","If you operate a self-hosted provider, align its version with what the schema expects.","Add fallback defaults for optional fields in the transform before validating."],"exampleFix":"// before\nJoi.object({ downloads: Joi.number().required() }) // data: { downloads: \"1,234\" } -> schema error\n// after\nJoi.object({ downloads: Joi.alternatives(Joi.number(), Joi.string().regex(/[\\d,]+/)).required() })","handlingStrategy":"validation","validationCode":"const { error, value } = schema.validate(data, { abortEarly: false, allowUnknown: true })\nif (error) console.warn('schema paths failing:', error.details.map(d => d.path).join(', '))","typeGuard":"function passesSchema(data, schema) { return !schema.validate(data, { abortEarly: false }).error }","tryCatchPattern":"try {\n  const value = validate({ ErrorClass: InvalidResponse, includeKeys: true }, data, schema)\n} catch (err) {\n  console.error('schema mismatch on:', err.underlyingError?.details?.map(d => d.path))\n  return fallbackBadge\n}","preventionTips":["Use includeKeys: true so failing paths appear in the message.","Write contract tests with recorded upstream fixtures.","Keep schemas in sync with upstream API changelogs.","Prefer lenient options (allowUnknown/stripUnknown) and only require what the badge needs."],"tags":["joi","validation","schema","upstream"],"backgroundTag":"schema-validation-failed","analyzedSha":"766fd8bc89a90b8534dc573ab72dec30215ab1ec","analyzedAt":"2026-08-30T01:40:27.499Z","schemaVersion":2},"datasetVersion":"2026-08-30T03:17:51.788Z"}