Skip to content

fix: show error message for duplicate env var keys - #5251

Merged
chronark merged 5 commits into
unkeyed:mainfrom
Felipeness:fix/show-duplicate-env-var-error
Mar 9, 2026
Merged

chronark merged 5 commits into
unkeyed:mainfrom
Felipeness:fix/show-duplicate-env-var-error

Conversation

@Felipeness

Copy link
Copy Markdown
Contributor

Summary

  • Fixed superRefine validation in schema.ts to mark all rows with duplicate keys (both first and subsequent occurrences), not just the second one. Previously, the first row with a duplicate key showed no error, leaving users confused about why the Save button was disabled.
  • Added a reason tooltip to the disabled Save button ("Fix validation errors above") so users understand why saving is blocked when validation errors exist.

How it works

The original code used a Map<string, number> to track the first seen index. When a duplicate was found, only the later row got an error via ctx.addIssue. The first row was silently stored in the map and never flagged.

The fix uses a Map<string, number[]> to collect all indices per compound key (environmentId::key). After the grouping pass, any group with more than one entry gets errors added to every row in the group.

Fixes #5219

Test plan

  • Create two env vars with the same key in the same environment
  • Verify both rows show the "Duplicate key in the same environment" error (not just the second one)
  • Verify the Save button tooltip shows "Fix validation errors above" when validation errors exist
  • Verify renaming one of the duplicate keys clears the error on both rows
  • Verify non-duplicate keys in different environments do not trigger false positives

The Zod superRefine validation already catches duplicate keys but
only marks the second occurrence. This change flags all rows with
the same key so users can see which entries conflict. Also adds a
reason tooltip to the disabled save button.

Fixes unkeyed#5219
@vercel

vercel Bot commented Mar 9, 2026

Copy link
Copy Markdown

@Felipeness is attempting to deploy a commit to the Unkey Team on Vercel.

A member of the Team first needs to authorize it.

@CLAassistant

CLAassistant commented Mar 9, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Mar 9, 2026 •

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fa2a8c15-90fe-403e-ba7c-53dea9caa051

📥 Commits

Reviewing files that changed from the base of the PR and between c7eccde and 79ce8ef.

📒 Files selected for processing (1)
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/advanced-settings/env-vars/index.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/advanced-settings/env-vars/index.tsx

📝 Walkthrough

Walkthrough

Propagates react-hook-form's trigger from EnvVarsForm to EnvVarRow to prompt re-validation on environment changes; switches duplicate-key validation to a grouped pass that reports all duplicate indices; updates save-state to include reason "Fix validation errors above" when form is invalid.

Changes

Cohort / File(s) Summary
Form entry / Save UI
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/advanced-settings/env-vars/index.tsx
Forwards the form trigger prop into the env-vars form, invokes trigger("envVars") after removals, and sets save-state reason to "Fix validation errors above" when validation blocks saving.
Row component
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/advanced-settings/env-vars/env-var-row.tsx
Adds trigger: UseFormTrigger<EnvVarsFormValues> to props and calls trigger("envVars") alongside field.onChange when environment Select value changes to force re-validation.
Schema validation
web/apps/dashboard/app/(app)/[workspaceSlug]/projects/[projectId]/(overview)/settings/components/advanced-settings/env-vars/schema.ts
Reworks duplicate-key validation from per-item immediate checks to a grouped two-pass approach that collects indices by (environmentId,key) and emits "Duplicate key in the same environment" for every index in duplicated groups.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant User
participant EnvVarRow
participant EnvVarsForm
participant Validator
User->>EnvVarRow: change environment select
EnvVarRow->>EnvVarsForm: field.onChange(...) and trigger("envVars")
EnvVarsForm->>Validator: run validation for "envVars"
Validator->>EnvVarsForm: return validation results (including grouped duplicate errors)
EnvVarsForm->>User: update UI (errors, save-state reason)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description provides a clear summary of changes, explains the fix mechanism, and includes a test plan, but does not follow the repository template structure with required sections. Add the required template sections: 'Type of change', 'How should this be tested', and complete the 'Checklist' items to match repository standards.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: fixing the display of error messages for duplicate environment variable keys.
Linked Issues check ✅ Passed The PR fully addresses issue #5219 by implementing validation to display error messages on all duplicate env var key rows and adding a tooltip to the disabled Save button.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing duplicate env var key validation and displaying error messages as specified in issue #5219. No unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ogzhanolguncu ogzhanolguncu self-assigned this Mar 9, 2026
@vercel

vercel Bot commented Mar 9, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dashboard Ready Ready Preview, Comment Mar 9, 2026 1:05pm

Request Review

@ogzhanolguncu ogzhanolguncu left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works great, we just have to trigger validation again and get rid of the stale error. This only happens when changes(changing variables' environment). Check out the video

Screen.Recording.2026-03-09.at.14.24.53.mov

Clear stale duplicate-key errors when a variable's environment
is changed, since the compound key includes the environment ID.

Addresses review feedback on unkeyed#5251

@Felipeness Felipeness left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching that and for the video — it made the issue super clear! The root cause was that changing the environment didn't re-trigger the array-level superRefine validation, so the stale error stuck around. I've pushed a fix (trigger("envVars") on environment change) to force re-validation when the variable's environment is updated. Could you give it another look when you get a chance?

Merge upstream changes (RemoveButton import from unkeyed#5211) with our
UseFormTrigger addition, keeping both imports.
useFieldArray.remove() does not re-trigger array-level superRefine
validation, so removing one of two duplicate rows left the remaining
row showing a stale "Duplicate key" error. Calling trigger("envVars")
after remove() forces re-validation and clears the error.
@Felipeness

Copy link
Copy Markdown
Contributor Author

While auditing the code for this PR, I also noticed a pre-existing issue in the env vars component: the React key for EnvVarRow includes the array index (${field.id}-${index}), which goes against react-hook-form's useFieldArray recommendation to use only field.id. This can cause local state loss (like the visibility toggle) when rows are deleted.

Opened a separate small PR for that: #5262. Not 100% sure it causes visible issues in practice, but just trying to help clean things up!

@chronark
chronark disabled auto-merge March 9, 2026 13:56
@chronark
chronark enabled auto-merge March 9, 2026 13:57
@chronark
chronark disabled auto-merge March 9, 2026 13:57
@chronark
chronark merged commit c501740 into unkeyed:main Mar 9, 2026
5 of 7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Show error when duplicate env var name blocks saving

5 participants