{"record":{"id":"d388ff0c1a58fd2e","repo":"jackwener/OpenCLI","slug":"nuget-package-registration-page-pageindex-1-i","errorCode":null,"errorMessage":"nuget package registration page ${pageIndex + 1} is missing @id for package \"${id}\"","messagePattern":"nuget package registration page (.+?) is missing @id for package \"(.+?)\"","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/nuget/package.js","lineNumber":49,"sourceCode":"        'listed',\n        'url',\n    ],\n    func: async (args) => {\n        const id = requirePackageId(args.id);\n        const url = `${NUGET_REGISTRATION_BASE}/${encodeURIComponent(id.toLowerCase())}/index.json`;\n        const body = await nugetFetch(url, 'nuget package');\n        const pages = Array.isArray(body?.items) ? body.items : [];\n        // Each page can be inline (with `items`) or a stub that needs another fetch\n        // for older packages. Inline is the common case for everything published in\n        // the last few years. We follow stub pages once each — at most ~5 round-trips.\n        const allEntries = [];\n        for (const [pageIndex, page] of pages.entries()) {\n            let pageItems = Array.isArray(page?.items) ? page.items : null;\n            if (!pageItems) {\n                // Stub page → fetch the leaf.\n                const pageUrl = typeof page?.['@id'] === 'string' ? page['@id'] : null;\n                if (!pageUrl) {\n                    throw new CommandExecutionError(\n                        `nuget package registration page ${pageIndex + 1} is missing @id for package \"${id}\"`,\n                    );\n                }\n                const leaf = await nugetFetch(pageUrl, 'nuget package page');\n                if (!Array.isArray(leaf?.items)) {\n                    throw new CommandExecutionError(\n                        `nuget package registration leaf ${pageUrl} did not include an items array`,\n                    );\n                }\n                pageItems = leaf.items;\n            }\n            for (const it of pageItems) {\n                if (!it || typeof it !== 'object' || !it.catalogEntry || typeof it.catalogEntry !== 'object') {\n                    throw new CommandExecutionError(\n                        `nuget package registration page ${pageIndex + 1} contains a malformed version entry`,\n                    );\n                }\n                allEntries.push(it);","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/nuget/package.js#L31-L67","documentation":"When building nuget package registration metadata, the code paginates through the NuGet registration API. Each page should carry an '@id' string URL pointing to the leaf page containing its items. If a page object has no items array and also lacks a usable '@id', the adapter cannot resolve that page, so it throws CommandExecutionError. This guards against malformed or unexpected registration payloads from the NuGet service.","triggerScenarios":"nugetFetch of a package registration index where an element of pages[] is neither a flat page (missing items array) nor a stub (missing or non-string '@id') — e.g. the NuGet API returns null page entries, an empty object, or '@id' of a type other than string for the package being queried.","commonSituations":"Packages with very many versions that produce deeply paginated registration indexes where stub pages are expected; NuGet API schema drift or partial outage returning incomplete registration documents; proxies/CDNs truncating the registration JSON so later pages come back as empty objects.","solutions":["Retry the request — incomplete registration payloads from a partial NuGet response often resolve on retry","Verify the package's registration index directly: GET https://api.nuget.org/v3/registration5-gz-semver2/<id>/index.json (with appropriate content encoding) and inspect page '@id' values","Check https://status.nuget.org for a NuGet service incident if the payload looks systematically malformed","If it persists for a specific package, the index may be corrupt on the service side — report it to NuGet or fall back to the flat container API for version listing"],"exampleFix":"// before\nconst index = await nugetFetch(registrationUrl, 'nuget registration');\nconst versions = collectVersions(index);\n// after\nconst index = await nugetFetch(registrationUrl, 'nuget registration');\nconst pages = (index?.pages ?? []).filter((p) => Array.isArray(p?.items) || typeof p?.['@id'] === 'string');\nif (!pages.length) {\n  console.error('NuGet registration index had no resolvable pages; retrying or using flat container API.');\n}\nconst versions = collectVersions({ pages });","handlingStrategy":"validation","validationCode":"function hasResolvablePages(index) {\n  return Array.isArray(index?.pages) && index.pages.every(\n    (p) => Array.isArray(p?.items) || typeof p?.['@id'] === 'string'\n  );\n}\nconst index = await nugetFetch(registrationUrl, 'nuget registration');\nif (!hasResolvablePages(index)) throw new Error('Registration index has unresolvable pages');","typeGuard":"function isResolvablePage(page) {\n  return page != null &&\n    (Array.isArray(page.items) || typeof page['@id'] === 'string');\n}","tryCatchPattern":"try {\n  const data = await collectVersions(id);\n  return data;\n} catch (err) {\n  if (String(err.message).includes('is missing @id')) {\n    console.error('NuGet returned an incomplete registration index; retry or use the flat container API.');\n    return null;\n  }\n  throw err;\n}","preventionTips":["Validate every registration page shape (items array or '@id' string) before walking pages","Check https://status.nuget.org when registration payloads look incomplete","Retry truncated/incomplete payloads — NuGet edge responses can be cut short under load","Fall back to the flat container API (api.nuget.org/v3-flatcontainer/<id>/index.json) when the registration index is unusable"],"tags":["nuget","registration-api","missing-field","data-integrity"],"backgroundTag":"missing-required-field","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}