tailwindlabs/tailwindcss · error · Error

`@source` paths must be quoted.

Error message

`@source` paths must be quoted.

What it means

Thrown when the resolved `@source` path does not start and end with matching quotes. After stripping optional `not ` and `inline(...)` wrappers, the remaining path is checked the same way as `source(…)` — it must be a quoted string literal. The `not ` and `inline(...)` keywords themselves are detected by prefix checks before this guard.

Source

Thrown at packages/tailwindcss/src/index.ts:286

      let inline = false
      let path = node.params

      if (path[0] === 'n' && path.startsWith('not ')) {
        not = true
        path = path.slice(4)
      }

      if (path[0] === 'i' && path.startsWith('inline(')) {
        inline = true
        path = path.slice(7, -1).trim()
      }

      if (
        (path[0] === '"' && path[path.length - 1] !== '"') ||
        (path[0] === "'" && path[path.length - 1] !== "'") ||
        (path[0] !== "'" && path[0] !== '"')
      ) {
        throw new Error('`@source` paths must be quoted.')
      }

      let source = path.slice(1, -1)

      if (inline) {
        let destination = not ? ignoredCandidates : inlineCandidates
        let sources = segment(source, ' ')
        for (let source of sources) {
          for (let candidate of expand(source)) {
            destination.push(candidate)
          }
        }
      } else {
        sources.push({
          base: ctx.context.base as string,
          pattern: source,
          negated: not,
        })

View on GitHub (pinned to 16e94cbf7f)

Solutions

  1. Quote the path: `@source "./src/**/*.html"`.
  2. When negating or inlining, quote the inner path: `@source not("./legacy/**")`, `@source inline("./file.html")`.
  3. Use `@source none` only if you intend to disable all automatic source detection (note: `@source none` is not the keyword form — disable scanning via the build config instead).

Example fix

/* before */
@source not(./legacy/**);
@source inline(./icons.svg);

/* after */
@source not("./legacy/**");
@source inline("./icons.svg");
Defensive patterns

Strategy: validation

Validate before calling

// Reproduce the library's quoting check after stripping not/inline wrappers.
function validateSourceQuoted(raw: string): string | null {
  let path = raw.trim()
  if (path.startsWith('not ')) path = path.slice(4).trim()
  if (path.startsWith('inline(')) path = path.slice(7, -1).trim()
  const ok = (path.startsWith('"') && path.endsWith('"')) ||
             (path.startsWith("'") && path.endsWith("'"))
  return ok ? null : `@source path '${raw}' must be quoted`
}

Prevention

When it happens

Trigger: Writing `@source ./src/**/*.html` (unquoted), `@source not(./legacy/**)`, or `@source inline(./file.html)`. Each requires the inner path to be quoted.

Common situations: Copy-pasting glob examples that lost quotes; mixing up `@source` syntax with shell-style unquoted globs.

Related errors


AI-assisted analysis of tailwindlabs/tailwindcss@16e94cbf7f (2026-08-12). Data as JSON: /api/errors/151bed5c129b94eb. Report an issue: GitHub.