nodejs/node · error · Error

GitLab CI/CD pipeline file must be just a file not a path

Error message

GitLab CI/CD pipeline file must be just a file not a path

What it means

Thrown by GitLab trust provider's validateFile() when the --file value is not equal to its own path.basename, i.e. it contains path separators. GitLab's trusted-publishing claim references a single top-level pipeline filename inside the project, not an arbitrary relative path, so a value like 'ci/pipeline.yml' or './.gitlab-ci.yml' is rejected before optionsToBody builds the ci_config_ref_uri.

Source

Thrown at deps/npm/lib/commands/trust/gitlab.js:65

    globalDefinitions.yes,
  ]

  getEntityUrl ({ providerHostname, file, entity }) {
    if (file) {
      return new URL(`${entity}/-/blob/HEAD/${file}`, providerHostname).toString()
    }
    return new URL(entity, providerHostname).toString()
  }

  validateEntity (entity) {
    if (entity.split('/').length < 2) {
      throw new Error(`${this.constructor.providerEntity} must be specified in the format group/project or group/subgroup/project`)
    }
  }

  validateFile (file) {
    if (file !== path.basename(file)) {
      throw new Error('GitLab CI/CD pipeline file must be just a file not a path')
    }
  }

  static optionsToBody (options) {
    const { file, project, environment } = options
    const trustConfig = {
      type: 'gitlab',
      claims: {
        project_path: project,
        // this looks off, but this is correct
        /** 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. */
        ci_config_ref_uri: {
          file,
        },
        ...(environment) && { environment },
      },
    }
    return trustConfig

View on GitHub (pinned to 1b2de5e052)

Solutions

  1. Use just the filename, e.g. `--file .gitlab-ci.yml`, and ensure the file sits at the repository root.
  2. If you genuinely need a nested pipeline file, move/include it at the repo root since GitLab trusted publishing only supports top-level files.
  3. Strip any './' prefix or directory component before passing the value.

Example fix

// before
npm trust gitlab --file ci/.gitlab-ci.yml --project group/proj
// after
npm trust gitlab --file .gitlab-ci.yml --project group/proj
Defensive patterns

Strategy: validation

Validate before calling

const path = require('node:path')
const assertPipelineFile = (file) => {
  if (file !== path.basename(file)) {
    throw new TypeError(`Pipeline file must be a bare filename, got: ${file}`)
  }
}

Type guard

const path = require('node:path')
const isBareFilename = (v) => typeof v === 'string' && v === path.basename(v)

Try / catch

try {
  await trustGitlab.exec([...])
} catch (err) {
  if (/must be just a file/i.test(err.message)) {
    // strip the directory component and retry with path.basename(file)
  } else { throw err }
}

Prevention

When it happens

Trigger: Calling `npm trust gitlab --file ci/.gitlab-ci.yml ...` or `--file ./config/pipeline.yaml`. Also triggered by a leading './' since basename strips it but the raw string differs. validateFile runs after the .yml/.yaml extension check in flagsToOptions.

Common situations: Migrating from a CI setup where the pipeline lives in a subfolder; assuming the flag accepts a path like most CLI file flags; IDE autocomplete inserting a relative path.

Related errors


AI-assisted analysis of nodejs/node@1b2de5e052 (2026-08-13). Data as JSON: /api/errors/450d8d7b1d0450fc. Report an issue: GitHub.