{"record":{"id":"d388534f7ce1e79b","repo":"abhigyanpatwari/GitNexus","slug":"links-i-type-link-type-is-invalid-expect","errorCode":null,"errorMessage":"links[${i}].type \"${link.type}\" is invalid. Expected: ${VALID_CONTRACT_TYPES.join(', ')}","messagePattern":"links\\[(.+?)\\]\\.type \"(.+?)\" is invalid\\. Expected: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"gitnexus/src/core/group/config-parser.ts","lineNumber":75,"sourceCode":"  if (!raw.name || typeof raw.name !== 'string') throw new Error('name is required in group.yaml');\n  if (!raw.repos || typeof raw.repos !== 'object' || Array.isArray(raw.repos)) {\n    throw new Error('repos is required in group.yaml (must be a mapping)');\n  }\n\n  const repos = raw.repos as Record<string, string>;\n  const repoPaths = new Set(Object.keys(repos));\n\n  const rawLinks = (raw.links as unknown[]) || [];\n  const links: GroupManifestLink[] = rawLinks.map((l: unknown, i: number) => {\n    const link = l as Record<string, unknown>;\n    if (!link.from || !repoPaths.has(link.from as string)) {\n      throw new Error(`links[${i}].from \"${link.from}\" does not match any repo path in group`);\n    }\n    if (!link.to || !repoPaths.has(link.to as string)) {\n      throw new Error(`links[${i}].to \"${link.to}\" does not match any repo path in group`);\n    }\n    if (!VALID_CONTRACT_TYPES.includes(link.type as ContractType)) {\n      throw new Error(\n        `links[${i}].type \"${link.type}\" is invalid. Expected: ${VALID_CONTRACT_TYPES.join(', ')}`,\n      );\n    }\n    if (!VALID_ROLES.includes(link.role as ContractRole)) {\n      throw new Error(`links[${i}].role \"${link.role}\" is invalid. Expected: provider | consumer`);\n    }\n    if (\n      link.contract === undefined ||\n      link.contract === null ||\n      String(link.contract).trim() === ''\n    ) {\n      throw new Error(`links[${i}].contract is required`);\n    }\n    return {\n      from: link.from as string,\n      to: link.to as string,\n      type: link.type as ContractType,\n      contract: String(link.contract),","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/gitnexus/src/core/group/config-parser.ts#L57-L93","documentation":"Thrown during links[] validation when a link's 'type' field is not one of the allowed contract types. VALID_CONTRACT_TYPES is a closed enum: http, grpc, thrift, topic, lib, custom, include. The message lists all valid values so the fix is mechanical. Note the enum is case-sensitive lowercase.","triggerScenarios":"A link with type: 'HTTP' (wrong case), type: 'rest', type: 'websocket', or any value outside the seven allowed; a link missing the 'type' field entirely (undefined is not in the enum).","commonSituations":"Wrong-case typo (HTTP vs http); inventing a contract type not yet supported; copy-paste from docs that used a synonym; missing type field in a hand-authored link.","solutions":["Set the link.type to one of: http, grpc, thrift, topic, lib, custom, include (lowercase, exact).","If your contract doesn't fit any of these, use 'custom' as the catch-all.","For C/C++ header includes, use 'include' (and enable detect.includes in the group)."],"exampleFix":"# before — wrong case\nlinks:\n  - { from: services/api, to: services/worker, type: HTTP, contract: GET /v1, role: provider }\n\n# after\nlinks:\n  - { from: services/api, to: services/worker, type: http, contract: GET /v1, role: provider }","handlingStrategy":"type-guard","validationCode":"const VALID_CONTRACT_TYPES = ['http','grpc','thrift','topic','lib','custom','include'] as const;\ntype ContractType = typeof VALID_CONTRACT_TYPES[number];\nfunction isContractType(v: unknown): v is ContractType {\n  return typeof v === 'string' && (VALID_CONTRACT_TYPES as readonly string[]).includes(v);\n}","typeGuard":"function isContractType(v: unknown): v is ContractType {\n  return typeof v === 'string' && ['http','grpc','thrift','topic','lib','custom','include'].includes(v);\n}","tryCatchPattern":null,"preventionTips":["Use lowercase exact values from the enum when authoring links.","Default unknown contract categories to 'custom' rather than inventing a type.","Add a YAML schema or JSON Schema for group.yaml so editors flag invalid type values."],"tags":["yaml","group-config","links","validation","contract-type","config-parser"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}