vitest-dev/vitest · error

Unknown value for "test.listTags

Error message

Unknown value for "test.listTags": ${listTags}

What it means

The `test.listTags` option accepts a strict union: a boolean (`true`/`false`) to print tags as plain text, or the literal string `'json'` to emit a machine-readable manifest. Any other value (a number, an object, an unrecognised string) reaches the final `else` branch and is rejected.

Solutions

  1. Use `listTags: true` for the default text output or `listTags: 'json'` for JSON.
  2. If sourcing the value from an env var, coerce explicitly: `listTags: process.env.LIST_TAGS === 'json' ? 'json' : Boolean(process.env.LIST_TAGS)`.
  3. Leave the option unset if you do not want tag listing.

Example fix

// before
listTags: 'true'
// after
listTags: true
Defensive patterns

Strategy: type-guard

Validate before calling

function normaliseListTags(v: unknown): boolean | 'json' | undefined {
  if (v === 'json') return 'json'
  if (typeof v === 'boolean') return v
  throw new Error(`listTags must be boolean or 'json', received: ${String(v)}`)
}
config.test.listTags = normaliseListTags(process.env.LIST_TAGS)

Type guard

function isValidListTags(v: unknown): v is boolean | 'json' {
  return v === 'json' || typeof v === 'boolean'
}

Prevention

When it happens

Trigger: Setting `listTags: 'yes'`, `listTags: 1`, `listTags: { format: 'json' }`, or any value that is neither boolean nor `'json'`.

Common situations: Treating the option as a free-form string; copy-pasting from docs that used a different spelling; env-var coercion turning 'true' into the string value 'true' instead of a boolean.

Related errors


AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11). Data as JSON: /api/errors/44a7677979fd77a3. Report an issue: GitHub.

Appendix: source

Thrown at packages/vitest/src/node/core.ts:497

    else if (listTags === 'json') {
      const hasTags = [this.getRootProject(), ...this.projects].some(p => p.config.tags && p.config.tags.length > 0)
      if (!hasTags) {
        process.exitCode = 1
        this.logger.printNoTestTagsFound()
      }
      else {
        const manifest = {
          tags: this.config.tags,
          projects: this.projects.filter(p => p !== this.coreWorkspaceProject).map(p => ({
            name: p.name,
            tags: p.config.tags,
          })),
        }
        this.logger.log(JSON.stringify(manifest, null, 2))
      }
    }
    else {
      throw new Error(`Unknown value for "test.listTags": ${listTags}`)
    }
  }

  public async enableCoverage(): Promise<void> {
    this.configOverride.coverage = {} as any
    this.configOverride.coverage!.enabled = true
    await this.createCoverageProvider()
    await this.coverageProvider?.onEnabled?.()

    // onFileTransform is the only thing that affects hash
    if (this.coverageProvider?.onFileTransform) {
      this.clearAllCachePaths()
    }
  }

  public disableCoverage(): void {
    this.configOverride.coverage ??= {} as any
    this.configOverride.coverage!.enabled = false

View on GitHub (pinned to 1fa9837ec2)