Skip to content

refactor(errors): extract shared errorMessage() helper (PP-uufe) - #2112

Merged
timothyfroehlich merged 1 commit into
mainfrom
claude/vibrant-faraday-sckbjb
Sep 18, 2026
Merged

timothyfroehlich merged 1 commit into
mainfrom
claude/vibrant-faraday-sckbjb

Conversation

@timothyfroehlich

@timothyfroehlich timothyfroehlich commented Sep 13, 2026 •

Copy link
Copy Markdown
Owner

Summary

Extracts a single pure helper errorMessage(error, fallback?) (src/lib/errors.ts) to replace 21 hand-rolled repetitions of the error instanceof Error ? error.message : X idiom across the codebase. Addresses the DRY item tracked in PP-uufe (from the PP-ywcr dedup survey).

The helper

export function errorMessage(error: unknown, fallback?: string): string {
  if (error instanceof Error) return error.message;
  return fallback ?? String(error);
}

Design note: the bead proposed a literal fallback = "Unknown" default. I used an optional fallback that defaults to String(error) instead, because the call sites fell into two families — string-literal fallbacks (: "Unknown", : "Upload failed", …) and String(err) fallbacks. A hard "Unknown" default could not replace the String(err) family without changing behavior; the optional-String() default preserves exact semantics at every site (literal sites pass their literal; String(err) sites call errorMessage(err) bare). Uses ?? (not ||) so an explicit empty-string fallback is honored.

Scope — what was deliberately NOT changed

Four remaining ternaries have a raw-value fallback (: error / : dbError / : parseError) that is logged into a structured err field — logger.ts, report/actions.ts (×2), report/(tabbed)/quick/actions.ts. A string-typed helper would coerce the object to "[object Object]" and discard the payload the logger serializes, so these are left as-is. Guard expressions (instanceof Error && …) are not the target idiom and are untouched. No behavior changes anywhere — every conversion is 1:1 equivalent to the ternary it replaced.

Testing

  • typecheck, typecheck:tests, lint (oxlint), prettier — all clean.
  • New unit test src/lib/errors.test.ts (6 cases) + full unit suite: 2727 pass. The 5 failures in src/test/unit/scripts/db-target-guards.test.ts are subprocess-spawn timeouts specific to this cloud sandbox — unrelated to this diff (no scripts/ files touched) and green in CI.
  • Adversarially reviewed via three independent lenses (correctness / bead-fidelity / maintainability); all returned clean.

Refs PP-uufe.

🤖 Generated with Claude Code

https://claude.ai/code/session_0131WEJgWBmXWjoZ1qYfLsWJ


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Added consistent error-message formatting across account management, authentication, uploads, cleanup, rate limiting, and location synchronization workflows.
    • Standardized fallback messages for unexpected or non-standard errors.
  • Bug Fixes

    • Improved failure logging and user-facing error responses when errors are not standard Error objects.
  • Tests

    • Added coverage for error messages, fallbacks, string values, subclasses, and empty fallback behavior.

Replace 21 repetitions of the `error instanceof Error ? error.message : X`
idiom with a single pure helper `errorMessage(error, fallback?)` in
src/lib/errors.ts.

- String-literal fallback sites pass their literal explicitly.
- Sites that previously fell back to `String(err)` now call
  `errorMessage(err)` bare; the helper defaults the fallback to
  `String(error)` so non-Error throws still surface something readable.
- Raw-value fallback sites (`: error` / `: dbError`, logged as structured
  fields) are intentionally left unconverted — a string-typed helper would
  discard the object payload the logger serializes.

Adds unit coverage in src/lib/errors.test.ts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0131WEJgWBmXWjoZ1qYfLsWJ
@timothyfroehlich timothyfroehlich added the ownerless Opened by an unattended agent (routine, Dependabot, Renovate); needs pickup label Sep 13, 2026 — with Claude
@vercel

vercel Bot commented Sep 13, 2026 •

Copy link
Copy Markdown

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

Project Deployment Actions Updated
pin-point Ready Ready Preview Sep 13, 2026 7:56am UTC

Request Review

@timothyfroehlich timothyfroehlich removed the ownerless Opened by an unattended agent (routine, Dependabot, Renovate); needs pickup label Sep 14, 2026
@timothyfroehlich

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@timothyfroehlich

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Sep 18, 2026 •

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai

coderabbitai Bot commented Sep 18, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

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: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 469c432b-b156-4b15-87f6-f5c31c07d8ce

📥 Commits

Reviewing files that changed from the base of the PR and between 5bd3ee7 and 200040d.

📒 Files selected for processing (15)
  • src/app/(app)/admin/users/actions.ts
  • src/app/(app)/admin/users/remove-invited-user-button.tsx
  • src/app/(app)/admin/users/resend-invite-button.tsx
  • src/app/(app)/admin/users/user-role-select.tsx
  • src/app/(auth)/actions.ts
  • src/app/api/test-data/cleanup/route.ts
  • src/app/api/test-setup/route.ts
  • src/lib/auth/profile.ts
  • src/lib/blob/cleanup.ts
  • src/lib/blob/client.ts
  • src/lib/errors.test.ts
  • src/lib/errors.ts
  • src/lib/pinballmap/state.ts
  • src/lib/rate-limit.ts
  • src/server/actions/images.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 7 remain after this review.

📜 Recent review details
🧰 Additional context used
🪛 ast-grep (0.45.3)
src/lib/rate-limit.ts

[warning] 331-338: Avoid logging sensitive data
Context: log.error(
keyType === "email"
? { err, email: maskEmail(limitKey) }
: keyType === "user"
? { err, userKeyPrefix: normalizedKey.slice(0, 8) }
: { err, ip: limitKey },
${label} rate limit check failed
)
Note: [CWE-532] Insertion of Sensitive Information into Log File.

(log-sensitive-data-typescript)

🔇 Additional comments (7)
src/app/(app)/admin/users/actions.ts (1)

18-18: LGTM!

Also applies to: 248-248, 413-413, 478-478, 560-560

src/app/(app)/admin/users/remove-invited-user-button.tsx (1)

18-18: LGTM!

Also applies to: 39-39

src/app/(app)/admin/users/resend-invite-button.tsx (1)

6-6: LGTM!

Also applies to: 28-28

src/lib/blob/client.ts (1)

6-6: LGTM!

Also applies to: 79-79, 138-138

src/lib/pinballmap/state.ts (1)

5-5: LGTM!

Also applies to: 551-551, 691-691

src/lib/rate-limit.ts (1)

25-25: LGTM!

Also applies to: 331-331

src/server/actions/images.ts (1)

19-19: LGTM!

Also applies to: 237-237, 255-255, 259-259


📝 Walkthrough

Walkthrough

The pull request adds the shared errorMessage helper and replaces local error-to-string checks across application, server, and library error paths. Tests cover Error values, fallbacks, stringification, and empty fallbacks.

Changes

Shared Error Formatting

Layer / File(s) Summary
Error formatter and tests
src/lib/errors.ts, src/lib/errors.test.ts
Adds errorMessage and tests Error messages, fallbacks, stringification, and empty fallback values.
Application error paths
src/app/(app)/admin/users/*, src/app/(auth)/actions.ts, src/app/api/test-data/cleanup/route.ts, src/app/api/test-setup/route.ts
Replaces local instanceof Error handling in admin actions, UI handlers, authentication logging, and test routes. Existing fallback messages and response behavior remain.
Library and server error paths
src/lib/auth/profile.ts, src/lib/blob/*, src/lib/pinballmap/state.ts, src/lib/rate-limit.ts, src/server/actions/images.ts
Uses errorMessage for logging and returned upload or route error messages. Existing operation behavior remains.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~12 minutes

Change: Refactor

Merge Risk: ⚪ Minimal · up to 20004

The refactor preserves existing error messages and fallbacks across the updated paths, with focused helper coverage in place. No actionable merge risk remains.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.91% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 22 functions across 15 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: extracting a shared errorMessage() helper for error handling.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR

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

@timothyfroehlich

Copy link
Copy Markdown
Owner Author

Antigravity review of head 200040d — two-axis review — CodeRabbit clean review (200040d) + local verification passed

@timothyfroehlich timothyfroehlich added the ready-for-review PR passed CI and has no unresolved review comments label Sep 18, 2026
@timothyfroehlich
timothyfroehlich merged commit 3bb9619 into main Sep 18, 2026
23 checks passed
@timothyfroehlich
timothyfroehlich deleted the claude/vibrant-faraday-sckbjb branch September 18, 2026 21:21

This branch was successfully deployed

1 active deployment
Preview — 200040d2 Deployed Sep 13, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-review PR passed CI and has no unresolved review comments

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants