Skip to content

Env files with indented, spaced, or Windows-line-ending Clerk lines get duplicate keys appended #555

Open

Description

@shane-kercheval

What happens

The CLI reads an env file line only when the variable name starts the line and = follows it directly (KEY=value, optionally with export). The loaders that frameworks use, such as dotenv in Next.js, accept more. When the CLI writes Clerk keys into a file whose existing Clerk line it doesn't recognize, it leaves that line in place and appends a second definition under a # Clerk header.

How the CLI reads each line shape today:

Line What the CLI does
KEY=value reads it
export KEY=value reads it
KEY=value (indented) ignores it
KEY = value (spaces around =) ignores it
KEY=value in a file with Windows line endings (CRLF) ignores it
KEY=value # note reads the value as value # note
KEY= value reads the value as value, keeping the leading space

In a file saved with Windows line endings, the CLI ignores every line.

Who hits it

Anyone whose env file holds Clerk keys in one of the ignored shapes, when they run:

  • clerk env pull, which writes keys into the file;
  • clerk init, which writes keys through the same step and also writes its own route variables.

Windows line endings are the most likely trigger, for example a file created on Windows or copied through a Windows tool.

The CLI's other readers of env files skip the same lines, so they don't see those keys either: matching a project's key to an app in clerk link and clerk init, and the key checks in clerk doctor.

What the person experiences

  • The command succeeds.
  • The file now defines each Clerk key twice: the old line, then a new line under # Clerk.
  • Which value the app uses depends on the framework's loader, so the old keys may still win.
  • clerk link and clerk init may fail to match the project to its app, because they don't see the key.

How big a deal it is

  • How often: unknown. Windows line endings are the likeliest cause. Hand-formatted lines (indented or spaced) are rarer.
  • How bad when it happens: low to medium. Nothing is lost, but the file is left with duplicate keys, and the app may keep running on the old ones.
  • Does it block them: no.

Proposed fix

  • Read env lines the way the frameworks' loaders do: allow leading whitespace and spaces around =, strip a trailing \r, trim unquoted values, and drop a trailing # comment from unquoted values. Where loaders disagree, read conservatively.
  • When rewriting a key, replace the line the loader would read, keeping the file's other formatting and comments, instead of appending.

Where it goes: parseEnvFile and mergeEnvVars in packages/cli-core/src/lib/dotenv.ts. hasClerkKeys in packages/cli-core/src/commands/env/pull.ts uses its own, looser pattern and should share the same reader.

Tests

  • Each line shape in the table above, read with the right value.
  • Each shape rewritten in place, with no duplicate appended.
  • A file with Windows line endings read and rewritten correctly.

Reproduce

  1. In a Next.js project, create .env.local with Windows line endings:
    printf 'NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_old\r\nCLERK_SECRET_KEY=sk_test_old\r\n' > .env.local
  2. Link the project to an app and run clerk env pull.
  3. Open .env.local. The original two lines are still there, followed by a blank line, # Clerk, and the two keys again.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions