{"record":{"id":"ff5a03e8855e7898","repo":"canopy-network/canopy","slug":"could-not-find-types-proto-descriptor","errorCode":null,"errorMessage":"Could not find types.proto descriptor","messagePattern":"Could not find types\\.proto descriptor","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugin/typescript/scripts/generate-descriptors.cjs","lineNumber":86,"sourceCode":"        const enumMatches = content.matchAll(/^enum\\s+(\\w+)\\s*\\{/gm);\n        \n        fileTypes[protoFile] = {\n            messages: [...messageMatches].map(m => m[1]),\n            enums: [...enumMatches].map(m => m[1]),\n        };\n    }\n    \n    // Find the consolidated types.proto descriptor\n    let typesDescriptor = null;\n    for (const file of descriptorSet.file) {\n        if (file.name === 'types.proto') {\n            typesDescriptor = file;\n            break;\n        }\n    }\n    \n    if (!typesDescriptor) {\n        throw new Error('Could not find types.proto descriptor');\n    }\n    \n    // Create individual file descriptors by cloning and filtering\n    for (const protoFile of protoFiles) {\n        const types = fileTypes[protoFile];\n        \n        // Clone the descriptor and filter to only include types from this file\n        const fileDesc = {\n            name: protoFile,\n            package: typesDescriptor.package,\n            dependency: [],\n            messageType: [],\n            enumType: [],\n            syntax: typesDescriptor.syntax,\n            options: typesDescriptor.options,\n        };\n        \n        // Add google/protobuf/any.proto dependency if needed","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/canopy-network/canopy/blob/ee8197d91dd410f6592cb650a94c925ee6dc8bad/plugin/typescript/scripts/generate-descriptors.cjs#L68-L104","documentation":"The generate-descriptors.cjs build script compiles the proto directory into a consolidated descriptor set via protobufjs, then splits it back into per-file descriptors. It expects the compiled set to contain a file named exactly 'types.proto' (the name protobufjs consolidates under). If no descriptor file with that name is present in descriptorSet.file, the script throws this error, because the split step cannot proceed without it.","triggerScenarios":"Running `npm run build:descriptors` (or `make build-descriptors`) after the proto compilation step produced a descriptor set without a 'types.proto' entry — e.g. the pbjs/proto loader output was generated differently, the proto dir contents changed, or a stale/partial descriptor-set file is passed in.","commonSituations":"Re-running the descriptor build with a custom proto directory that renames types.proto; regenerating descriptors after editing the script's compilation step; using a different protobufjs version whose output file naming differs; a corrupted or outdated intermediate descriptor file left from a previous build.","solutions":["Re-run the full proto pipeline in order: `npm run build:proto` then `npm run build:descriptors` (or `make build-all`), so the descriptor set is regenerated fresh and contains the consolidated types.proto.","Verify the descriptor-compilation step in generate-descriptors.cjs actually loads all proto files from proto/ and check the descriptorSet.file names it produces (log them) to confirm whether 'types.proto' is missing or renamed.","If you renamed/moved types.proto in the proto directory, restore it or update the `file.name === 'types.proto'` lookup in the script to match the new name.","Clean stale build artifacts (generated index.js, descriptors output, intermediate descriptor set) and rebuild from a clean checkout."],"exampleFix":"// before (script looks only for types.proto)\nfor (const file of descriptorSet.file) {\n    if (file.name === 'types.proto') { typesDescriptor = file; break; }\n}\n// after (log available names to diagnose, fall back to first descriptor)\nconsole.log('descriptor files:', descriptorSet.file.map(f => f.name));\nfor (const file of descriptorSet.file) {\n    if (file.name === 'types.proto') { typesDescriptor = file; break; }\n}","handlingStrategy":"validation","validationCode":"const names = descriptorSet.file.map(f => f.name);\nif (!names.includes('types.proto')) {\n  throw new Error(`types.proto missing from descriptor set; got: ${names.join(', ')}`);\n}","typeGuard":"function hasTypesDescriptor(set) {\n  return Array.isArray(set?.file) && set.file.some(f => f?.name === 'types.proto');\n}","tryCatchPattern":"try {\n  buildDescriptors(descriptorSet);\n} catch (err) {\n  if (err.message.includes('Could not find types.proto')) {\n    console.error('Descriptor set malformed; re-run `npm run build:proto` first.', err.message);\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["Always run build:proto before build:descriptors (use make build-all).","Log descriptorSet.file names once in CI to catch renames early.","Never hand-edit the proto directory names that the script depends on.","Clean intermediate build artifacts when switching branches or protobufjs versions."],"tags":["build","protobuf","code-generation","nodejs"],"backgroundTag":"resource-not-found","analyzedSha":"ee8197d91dd410f6592cb650a94c925ee6dc8bad","analyzedAt":"2026-09-06T09:30:15.973Z","contentChangedAt":"2026-09-06T09:30:15.973Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}