{"record":{"id":"87d3786a0a18503b","repo":"nodejs/node","slug":"this-constructor-providerentity-must-be-specifi-87d378","errorCode":null,"errorMessage":"${this.constructor.providerEntity} must be specified in the format group/project or group/subgroup/project","messagePattern":"(.+?) must be specified in the format group/project or group/subgroup/project","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"deps/npm/lib/commands/trust/gitlab.js","lineNumber":59,"sourceCode":"    trustDefinitions['allow-publish'],\n    trustDefinitions['allow-stage-publish'],\n    // globals are alphabetical\n    globalDefinitions['dry-run'],\n    globalDefinitions.json,\n    globalDefinitions.registry,\n    globalDefinitions.yes,\n  ]\n\n  getEntityUrl ({ providerHostname, file, entity }) {\n    if (file) {\n      return new URL(`${entity}/-/blob/HEAD/${file}`, providerHostname).toString()\n    }\n    return new URL(entity, providerHostname).toString()\n  }\n\n  validateEntity (entity) {\n    if (entity.split('/').length < 2) {\n      throw new Error(`${this.constructor.providerEntity} must be specified in the format group/project or group/subgroup/project`)\n    }\n  }\n\n  validateFile (file) {\n    if (file !== path.basename(file)) {\n      throw new Error('GitLab CI/CD pipeline file must be just a file not a path')\n    }\n  }\n\n  static optionsToBody (options) {\n    const { file, project, environment } = options\n    const trustConfig = {\n      type: 'gitlab',\n      claims: {\n        project_path: project,\n        // this looks off, but this is correct\n        /** The ref path to the top-level pipeline definition, for example, gitlab.example.com/my-group/my-project//.gitlab-ci.yml@refs/heads/main. Introduced in GitLab 16.2. This claim is null unless the pipeline definition is located in the same project. */\n        ci_config_ref_uri: {","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/nodejs/node/blob/1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e/deps/npm/lib/commands/trust/gitlab.js#L41-L77","documentation":"Thrown by GitLab trust provider's validateEntity() when the project path passed via --project (or inferred from package.json) does not contain at least one '/'. The provider expects GitLab's 'group/project' or 'group/subgroup/project' namespace form so it can build a valid blob URL and a project_path claim. Because the check only counts segments, a bare project name or an empty string trips it.","triggerScenarios":"Running `npm trust gitlab --file .gitlab-ci.yml --project my-project` (no group), or passing an empty `--project`, or having a package.json repository like 'my-project' that resolves to a single-segment hosted-git-info repository used as the inferred project entity. validateEntity is called at the end of flagsToOptions after entity resolution.","commonSituations":"Copy-pasting just the repo name from GitLab's UI instead of the full namespaced path; a malformed repository string yielding one segment; forgetting the subgroup in deeply nested GitLab projects.","solutions":["Pass the full namespace: `--project group/my-project` (or `group/subgroup/my-project`).","Fix the package.json `repository` field to a GitLab URL or `gitlab:group/project` shorthand so inference yields two+ segments.","Verify the resolved entity with `npm trust gitlab ... --dry-run` before the real call; inspect what entity was inferred."],"exampleFix":"// before\nnpm trust gitlab --file .gitlab-ci.yml --project my-app\n// after\nnpm trust gitlab --file .gitlab-ci.yml --project my-group/my-app","handlingStrategy":"validation","validationCode":"const assertGitlabEntity = (entity) => {\n  if (typeof entity !== 'string' || entity.split('/').filter(Boolean).length < 2) {\n    throw new TypeError(`GitLab project must be group/project or group/subgroup/project, got: ${JSON.stringify(entity)}`)\n  }\n}\n// call before invoking the trust command programmatically\nassertGitlabEntity(process.env.NPM_TRUST_PROJECT)","typeGuard":"const isNamespacedGitlabPath = (v) =>\n  typeof v === 'string' && v.split('/').filter(Boolean).length >= 2","tryCatchPattern":"try {\n  await trustGitlab.exec([...])\n} catch (err) {\n  if (/group\\/project/i.test(err.message)) {\n    // prompt user for the full namespaced path and retry\n  } else { throw err }\n}","preventionTips":["Always copy the full GitLab project path including its group prefix.","In CI, derive the project path from $CI_PROJECT_PATH rather than hardcoding.","Validate the entity string in your wrapper script before invoking npm trust."],"tags":["validation","trust","gitlab","cli-args"],"backgroundTag":null,"analyzedSha":"1b2de5e052fc0fb95fd7fb6846dcec4ade598e9e","analyzedAt":"2026-08-13T00:53:24.642Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}