{"record":{"id":"dc7c2b0387e7b280","repo":"apple/pkl","slug":"sourcemodules-must-contain-at-least-one-module-n","errorCode":null,"errorMessage":"`sourceModules` must contain at least one module named `doc-package-info.pkl`, or an argument must be a package URI.","messagePattern":"`sourceModules` must contain at least one module named `doc-package-info\\.pkl`, or an argument must be a package URI\\.","errorType":"exception","errorClass":"CliException","httpStatus":null,"severity":"error","filePath":"pkl-doc/src/main/kotlin/org/pkl/doc/CliDocGenerator.kt","lineNumber":197,"sourceCode":"          try {\n            packageUris.add(PackageUri(moduleUri))\n          } catch (e: URISyntaxException) {\n            throw CliException(e.message!!)\n          }\n        }\n        else -> regularModuleUris.add(moduleUri)\n      }\n    }\n\n    if (docsiteInfoModuleUris.size > 1) {\n      throw CliException(\n        \"`sourceModules` contains multiple modules named `docsite-info.pkl`:\\n\" +\n          docsiteInfoModuleUris.joinToString(\"\\n\")\n      )\n    }\n\n    if (packageInfoModuleUris.isEmpty() && packageUris.isEmpty()) {\n      throw CliException(\n        \"`sourceModules` must contain at least one module named `doc-package-info.pkl`, or an argument must be a package URI.\"\n      )\n    }\n\n    if (regularModuleUris.isEmpty() && packageUris.isEmpty()) {\n      throw CliException(\n        \"`sourceModules` must contain at least one module to generate documentation for.\"\n      )\n    }\n\n    val builder = evaluatorBuilder()\n    var docsiteInfo: DocsiteInfo\n    val schemasByDocPackageInfoAndPath =\n      mutableMapOf<Pair<DocPackageInfo, Path>, MutableSet<ModuleSchema>>()\n    val schemasByDocPackageInfo = mutableMapOf<DocPackageInfo, Set<ModuleSchema>>()\n    // Evaluate module imports eagerly, which is cheap if docs are also generated for most imported\n    // modules.\n    // Alternatively, imports could be evaluated lazily,","sourceCodeStart":179,"sourceCodeEnd":215,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-doc/src/main/kotlin/org/pkl/doc/CliDocGenerator.kt#L179-L215","documentation":"pkl-doc requires either a module named `doc-package-info.pkl` among the `sourceModules`, or at least one argument that is a package URI, because package documentation metadata is what tells the generator what to document and how. Without either, there is no package context to generate docs for.","triggerScenarios":"Running `pkl-doc` where all `sourceModules` are regular modules (none named `doc-package-info.pkl`) and none of the arguments are package URIs (e.g. `package://...`).","commonSituations":"Documenting standalone modules without a doc-package-info.pkl; forgetting to include the package-info module when migrating from plain module docs; typo in the module file name (e.g. `docPackageInfo.pkl`).","solutions":["Add a `doc-package-info.pkl` module to the `sourceModules` arguments, or","Pass a package URI (e.g. `package://example.com/my/pkg@1.0.0`) as an argument","Rename/verify the package-info module is exactly named `doc-package-info.pkl`"],"exampleFix":"// before\npkl-doc mypkg/Module.pkl\n// after\npkl-doc mypkg/doc-package-info.pkl","handlingStrategy":"validation","validationCode":"val hasPkgInfo = sourceModules.any { it.fileName == \"doc-package-info.pkl\" }\nval hasPkgUri = args.any { it.startsWith(\"package://\") }\nrequire(hasPkgInfo || hasPkgUri) { \"Need a doc-package-info.pkl module or a package URI\" }","typeGuard":null,"tryCatchPattern":"try { pklDoc(args) } catch (e: CliException) { if (e.message?.contains(\"doc-package-info.pkl\") == true) { /* add package-info module */ } else throw e }","preventionTips":["Always include doc-package-info.pkl when documenting a package","Verify the exact file name spelling (kebab-case)","Decide up front between module-based and package-based doc generation"],"tags":["cli","missing-argument","validation"],"backgroundTag":"missing-required-argument","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}