Skip to content

fix: fall back to name lookup for UUID-shaped workspace names#24340

Merged
johnstcn merged 14 commits intomainfrom
fix/uuid-workspace-name-resolution
Apr 27, 2026
Merged

fix: fall back to name lookup for UUID-shaped workspace names#24340
johnstcn merged 14 commits intomainfrom
fix/uuid-workspace-name-resolution

Conversation

@johnstcn
Copy link
Copy Markdown
Member

@johnstcn johnstcn commented Apr 14, 2026

namedWorkspace in cli/root.go parsed workspace identifiers with uuid.Parse first and returned immediately on success, even when no workspace had that UUID as its actual ID. This caused 404 errors for any workspace whose name was a valid 32-char hex string (dashless UUID).

  • Add codersdk.ResolveWorkspace: tries UUID lookup first, falls back to name lookup on 404. NameValid guard skips the fallback for standard dashed UUIDs (36 chars > 32-char name limit).
  • Export codersdk.SplitWorkspaceIdentifier, replacing the duplicate splitNamedWorkspace in cli/root.go (uses strings.Cut).
  • Delete namedWorkspace from cli/root.go; all 28 call sites now use client.ResolveWorkspace directly.
  • Delete namedWorkspace and splitNameAndOwner from codersdk/toolsdk/bash.go; inline client.ResolveWorkspace.
  • Simplify GetWorkspace tool handler to a single ResolveWorkspace call.
  • Unit tests via httptest mock cover UUID, name, owner/name, UUID-like fallback, not-found, server error, transport error, and invalid identifier paths.
  • Integration tests in cli/show_test.go and codersdk/toolsdk for workspaces with UUID-like names.

Generated with Coder Agents

@johnstcn johnstcn changed the title fix(cli): fall back to name lookup for UUID-shaped workspace names fix: fall back to name lookup for UUID-shaped workspace names Apr 14, 2026
… name saga

Three packages had their own bespoke workspace-resolution logic with
varying levels of UUID handling, separator support, and error behavior.
Consolidate into a single codersdk.ResolveWorkspace method that does
UUID-first lookup with 404-fallback to name-based lookup.

- cli/root.go namedWorkspace now delegates to client.ResolveWorkspace
- toolsdk GetWorkspace handler: 15 lines become 1
- toolsdk bash.go namedWorkspace+splitNameAndOwner: deleted, replaced
  with single-line delegation
- Unit tests with httptest mock cover all resolution paths
splitWorkspaceIdentifier said "invalid workspace identifier" but
TestDelete/InvalidWorkspaceIdentifier expected "invalid workspace name".
Use "invalid workspace name" in both places for consistency.
- Rewrite stale toolsdk test comment that said "documents that bug"
  when the bug is now fixed
- Remove unused parsedUUID variable from test mock handler
- Replace context.Background() with t.Context() in all unit tests
  (Go 1.24+ convention)
- Add agent-backed WorkspaceBash regression coverage for UUID-like
  workspace names so bash/findWorkspaceAndAgent path is exercised
- Strengthen ResolveWorkspace negative-path unit tests to prove the
  fallback request happens and invalid identifiers fail before HTTP
- Refresh stale doc comments to match current behavior
@johnstcn johnstcn marked this pull request as ready for review April 15, 2026 08:43
Copilot AI review requested due to automatic review settings April 15, 2026 08:43
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes workspace resolution when the user supplies an identifier that parses as a UUID (including dashless 32-hex strings) but is actually intended to be a workspace name, by adding a shared SDK resolver with a 404-based fallback.

Changes:

  • Added codersdk.Client.ResolveWorkspace, which tries UUID lookup first and falls back to owner/name lookup on 404.
  • Updated CLI and toolsdk workspace lookup paths to delegate to ResolveWorkspace.
  • Added regression/unit tests covering UUID-like names across SDK, CLI, and toolsdk.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
codersdk/workspaces.go Introduces ResolveWorkspace + shared identifier splitting and 404 fallback logic.
codersdk/workspaces_test.go Adds focused unit tests for resolver behavior (UUID, name, owner/name, UUID-like fallback, errors).
codersdk/toolsdk/toolsdk.go Simplifies GetWorkspace tool handler to a single ResolveWorkspace call (with normalization).
codersdk/toolsdk/bash.go Removes now-redundant parsing/-- handling and delegates to ResolveWorkspace.
codersdk/toolsdk/toolsdk_test.go Adds regression tests ensuring tools resolve UUID-like workspace names correctly.
cli/root.go Updates namedWorkspace to delegate to SDK resolver (fixing CLI 404 regression).
cli/show_test.go Adds CLI regression test for showing a workspace whose name is a dashless UUID-like string.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@github-actions github-actions Bot added the stale This issue is like stale bread. label Apr 23, 2026
@github-actions github-actions Bot closed this Apr 27, 2026
@johnstcn johnstcn reopened this Apr 27, 2026
@johnstcn johnstcn removed the stale This issue is like stale bread. label Apr 27, 2026
@johnstcn
Copy link
Copy Markdown
Member Author

/coder-agents-review

Copy link
Copy Markdown

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

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

Solid fix for a real bug. The UUID-like name resolution, 404-only fallback, and error type discrimination are correct. Test coverage at three levels (unit, integration, regression) is thorough. The centralization into codersdk.ResolveWorkspace eliminates three separate UUID-parse-and-dispatch implementations.

3 P3, 2 P4, 5 Nit. The P3s are: duplicate parsing function (DEREM-2), require.Equal in HTTP handler goroutines (DEREM-3), missing transport-error test case (DEREM-4), and an error message that says "workspace name" when it means "identifier" (DEREM-7). None blocks the feature.

CI is failing on lint. The emdash at workspaces_test.go:128 (DEREM-1) is a contributing cause. The PR description says "single source of truth for workspace resolution," but splitWorkspaceIdentifier duplicates cli/root.go:splitNamedWorkspace (DEREM-2); consider consolidating or updating the description.

"The UUIDLikeNameFallback test is the gem: it proves the actual bug fix by verifying the UUID endpoint fires first, gets a 404, and the name endpoint catches the fall." (Bisky)

🤖 This review was automatically generated with Coder Agents.

Comment thread codersdk/workspaces_test.go Outdated
Comment thread codersdk/workspaces.go Outdated
Comment thread codersdk/workspaces_test.go Outdated
Comment thread codersdk/workspaces_test.go Outdated
Comment thread codersdk/workspaces.go Outdated
Comment thread cli/root.go Outdated
Comment thread codersdk/workspaces.go Outdated
Comment thread codersdk/workspaces.go
Comment thread codersdk/toolsdk/bash.go Outdated
Comment thread codersdk/workspaces.go Outdated
- Export SplitWorkspaceIdentifier, consolidate with cli splitNamedWorkspace
- Use strings.Cut instead of Split+switch
- Fix error message: 'workspace name' -> 'workspace identifier'
- Add NameValid guard to skip wasted fallback for dashed UUIDs
- Fix require in handler goroutines (use assert)
- Add TransportError test case
- Fix em-dash lint violation
- Inline namedWorkspace in toolsdk/bash.go
Add OwnerWithUUIDLikeName and Forbidden cases.
@johnstcn
Copy link
Copy Markdown
Member Author

/coder-agents-review

Copy link
Copy Markdown

@coder-agents-review coder-agents-review Bot left a comment

Choose a reason for hiding this comment

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

All 8 code fixes from round 1 verified against the new diff. CI green. The consolidation into SplitWorkspaceIdentifier and ResolveWorkspace is clean; zero references to the old functions remain. The NameValid guard correctly prevents wasted name-based round-trips for dashed UUIDs. DEREM-5 (empty owner/name gap) remains accepted as pre-existing.

1 P4, 1 Nit new this round. The P4 is a narrow test coverage gap (no error-path test for name-based resolution). The Nit is an unused struct field. Nothing blocking.

"The test suite with atomic hit counters is an effective pattern for verifying multi-step resolution logic." (Kite)

🤖 This review was automatically generated with Coder Agents.

Comment thread codersdk/workspaces_test.go Outdated
Comment thread codersdk/workspaces_test.go
Copy link
Copy Markdown
Member Author

@johnstcn johnstcn left a comment

Choose a reason for hiding this comment

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

self-reviewed

@johnstcn johnstcn merged commit d5a5be1 into main Apr 27, 2026
26 checks passed
@johnstcn johnstcn deleted the fix/uuid-workspace-name-resolution branch April 27, 2026 11:58
@github-actions github-actions Bot locked and limited conversation to collaborators Apr 27, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants