Skip to content

feat(calendar): typed error envelopes for validation/internal errors#1232

Open
evandance wants to merge 1 commit into
mainfrom
feat/errs-migrate-calendar
Open

feat(calendar): typed error envelopes for validation/internal errors#1232
evandance wants to merge 1 commit into
mainfrom
feat/errs-migrate-calendar

Conversation

@evandance
Copy link
Copy Markdown
Collaborator

@evandance evandance commented Jun 2, 2026

Summary

Calendar commands now emit structured, typed error envelopes for input-validation and internal failures, replacing the previous legacy/generic errors. Callers — including AI agents — get consistent exit codes and a machine-readable error shape, so "you passed bad input" is reliably distinguishable from "something failed internally".

API-response error paths (the handlers that interpret a calendar API response) keep the existing error envelope for now; they are marked with TODOs and will move to the typed shape together with the typed API-call path, to avoid leaving a half-typed API layer in this change.

Changes

  • Flag/argument validation across +agenda, +create, +freebusy, +rsvp, +room-find, +suggestion, and +update now returns typed validation errors with the offending flag attributed.
  • Internal failures (a missing field in a successful response, an unparseable API response) now return typed internal errors.
  • +room-find / +suggestion API responses are classified into typed API-error envelopes via the shared classifier. The success payload is no longer copied into the error detail (it was previously included there).
  • Validation that previously flowed through a shared flag-error helper is now emitted as a typed error directly at the call site.
  • API-call-boundary error handling retains the existing envelope for now, marked with TODOs.
  • Added unit tests asserting the typed error shapes (category/subtype, attributed flag, exit code). Pre-existing API-path tests are unchanged.

Test Plan

  • go build ./...
  • go vet ./shortcuts/calendar/...
  • go test ./shortcuts/calendar/... — all pass (new typed-shape tests + unchanged existing tests)
  • gofmt -l shortcuts/calendar/ — clean

Related Issues

Part of the ongoing effort to give CLI errors a typed, machine-readable envelope across domains. No linked issue.

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced error messages across calendar commands (agenda, create, free-busy, RSVP, room-find, suggestion, update) with more precise validation feedback and clearer error classification to help users identify and resolve issues faster.
  • Tests

    • Added comprehensive test coverage validating error handling and message accuracy across calendar command operations.

Calendar commands now surface validation and internal errors as structured,
typed error envelopes with consistent exit codes and a machine-readable
shape, so callers (and AI agents) can reliably tell bad input apart from
internal faults. API-response error paths keep the existing envelope for now
and will move to the typed shape together with the typed API-call path.
@evandance evandance added domain/calendar PR touches the calendar domain size/M Single-domain feat or fix with limited business impact feature labels Jun 2, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 2, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR migrates error handling across seven calendar shortcut commands from legacy output.* helpers to a typed errs.* error framework. Validation errors now use errs.NewValidationError with structured parameter binding, and API errors are classified via errs.NewAPIError, errs.NewInternalError, and errclass.BuildAPIError. Comprehensive tests validate the migrated error shapes.

Changes

Calendar Error Handling Migration to Typed Errors

Layer / File(s) Summary
Validation error migration imports and core logic
shortcuts/calendar/calendar_agenda.go, calendar_create.go, calendar_freebusy.go, calendar_rsvp.go, calendar_update.go, calendar_suggestion.go
Adds errs imports and converts all validation failures to structured errs.NewValidationError(...).WithParam(...) across input parsing (parseAttendees, parseFreebusyTimeRange, parseTimeRange), command validation, and execution-time checks for missing/invalid --start, --end, --event-id, and attendee IDs.
API error classification in room-find
shortcuts/calendar/calendar_room_find.go
parseRoomFindSlots and parseRoomFindAttendees return structured validation errors with --slot and attendee prefix parameters; callRoomFind wraps request errors via errs.WrapInternal, classifies HTTP status failures via errs.NewAPIError, handles JSON unmarshal failures via errs.NewInternalError, and routes API response codes through errclass.BuildAPIError.
API error classification in suggestion
shortcuts/calendar/calendar_suggestion.go
buildSuggestionRequest validates --start, --end, --exclude with typed errors; Validate applies comprehensive flag/range validation; Execute classifies runtime.DoAPI errors via errs.ProblemOf and errs.WrapInternal, handles HTTP status with errs.NewAPIError, handles JSON unmarshal with errs.NewInternalError, and routes API codes through errclass.BuildAPIError.
API error conversion TODO markers
shortcuts/calendar/calendar_agenda.go, calendar_freebusy.go, calendar_rsvp.go, calendar_update.go
Scattered TODO comments mark API error paths for future conversion to typed errs.* errors; the recursion-limit error in agenda's fetchInstanceViewRange is migrated to errs.NewInternalError.
Comprehensive test coverage for typed errors
shortcuts/calendar/calendar_test.go
Added 16 test functions validating typed error shapes (*errs.ValidationError, *errs.InternalError, *errs.APIError) with correct Subtype, Param, and API Code; includes targeted flag-level validation tests and direct execution tests to cover empty --event-id guards and API error classification paths.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • larksuite/cli#151: Introduces the RSVP shortcut (calendar_rsvp.go) that this PR now migrates to typed errs.NewValidationError error handling.
  • larksuite/cli#678: Modifies calendar_update.go for the calendar update command, directly related to the validateCalendarUpdate and executeCalendarUpdate typed-error migrations in this PR.
  • larksuite/cli#403: Changes calendar_suggestion.go error handling; this PR migrates the same file's runtime.DoAPI error classification and API response handling.

Suggested reviewers

  • hugang-lark
  • calendar-assistant

Poem

🐰 Calendar errors now typed and tame,
Validation flags wear their proper name,
From output fog to errs so clear,
Each API response finds its frontier,
Tests affirm what the migrations seek—
A cleaner error path, week by week! 🎯

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 45.16% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and specifically describes the main change: migration of calendar command errors to typed error envelopes for validation and internal failures.
Description check ✅ Passed The pull request description is comprehensive and well-structured, covering summary, detailed changes, test plan, and related context.
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.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/errs-migrate-calendar

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.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@c4c0438015798b18f1745a69167fde4343f89907

🧩 Skill update

npx skills add larksuite/cli#feat/errs-migrate-calendar -y -g

@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 2, 2026

Codecov Report

❌ Patch coverage is 28.73563% with 62 lines in your changes missing coverage. Please review.
✅ Project coverage is 69.27%. Comparing base (04932c2) to head (c4c0438).

Files with missing lines Patch % Lines
shortcuts/calendar/calendar_suggestion.go 13.04% 20 Missing ⚠️
shortcuts/calendar/calendar_room_find.go 23.80% 16 Missing ⚠️
shortcuts/calendar/calendar_create.go 28.57% 10 Missing ⚠️
shortcuts/calendar/calendar_update.go 50.00% 7 Missing ⚠️
shortcuts/calendar/calendar_freebusy.go 37.50% 5 Missing ⚠️
shortcuts/calendar/calendar_agenda.go 20.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1232      +/-   ##
==========================================
+ Coverage   69.22%   69.27%   +0.04%     
==========================================
  Files         635      635              
  Lines       59687    59691       +4     
==========================================
+ Hits        41320    41352      +32     
+ Misses      15033    15020      -13     
+ Partials     3334     3319      -15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
shortcuts/calendar/calendar_create.go (1)

39-68: ⚡ Quick win

Consider adding parameter context to parseAttendees errors.

The parseAttendees function returns typed validation errors (line 64) but does not include .WithParam(...) because it's called from multiple contexts (--attendee-ids in create, --add-attendee-ids in update). To preserve parameter attribution in the final error envelope, consider one of:

  1. Add a paramName string argument to parseAttendees and call .WithParam(paramName) on line 64
  2. Return the error as-is and let callers add the param via type assertion if needed

This would align with the PR's goal of structured parameter binding in validation errors.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shortcuts/calendar/calendar_create.go` around lines 39 - 68, parseAttendees
currently returns a typed validation error without parameter context; change its
signature to parseAttendees(attendeesStr string, currentUserId string, paramName
string) and, where you construct the validation error in the default case, call
.WithParam(paramName) on the errs.NewValidationError result; then update callers
(the create path using "--attendee-ids" and the update path using
"--add-attendee-ids") to pass the appropriate param name so the final error
envelope preserves parameter attribution.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@shortcuts/calendar/calendar_create.go`:
- Around line 217-220: The code currently wraps the typed *errs.ValidationError
returned by parseAttendees(attendeesStr, currentUserId) into a new
errs.NewValidationError, losing the original error type and nesting messages;
instead, return the parseAttendees error directly, and if you need parameter
context call WithParam("--attendee-ids") on the returned error via a type
assertion (e.g., if ve, ok := err.(*errs.ValidationError); ok { return
ve.WithParam("--attendee-ids") } else { return err }), or modify parseAttendees
to accept the parameter name so it can produce a validation error with the param
already set.

In `@shortcuts/calendar/calendar_update.go`:
- Around line 327-330: The code in calendar_update.go is wrapping the typed
*errs.ValidationError from parseAttendees into a new errs.NewValidationError
which loses the original type; change this to return the original error directly
(return err) or, if you need parameter context, type-assert err to
*errs.ValidationError and call .WithParam("--add-attendee-ids") before
returning, or alternatively update parseAttendees to accept a parameterName and
set the param there; specifically modify the block around parseAttendees(addStr,
"") to avoid creating a new ValidationError and preserve the original error
type.

---

Nitpick comments:
In `@shortcuts/calendar/calendar_create.go`:
- Around line 39-68: parseAttendees currently returns a typed validation error
without parameter context; change its signature to parseAttendees(attendeesStr
string, currentUserId string, paramName string) and, where you construct the
validation error in the default case, call .WithParam(paramName) on the
errs.NewValidationError result; then update callers (the create path using
"--attendee-ids" and the update path using "--add-attendee-ids") to pass the
appropriate param name so the final error envelope preserves parameter
attribution.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 795dec8c-fecd-4e85-a2e1-98f9a42a38de

📥 Commits

Reviewing files that changed from the base of the PR and between 04932c2 and c4c0438.

📒 Files selected for processing (8)
  • shortcuts/calendar/calendar_agenda.go
  • shortcuts/calendar/calendar_create.go
  • shortcuts/calendar/calendar_freebusy.go
  • shortcuts/calendar/calendar_room_find.go
  • shortcuts/calendar/calendar_rsvp.go
  • shortcuts/calendar/calendar_suggestion.go
  • shortcuts/calendar/calendar_test.go
  • shortcuts/calendar/calendar_update.go

Comment on lines 217 to 220
attendees, err := parseAttendees(attendeesStr, currentUserId)
if err != nil {
return output.ErrValidation("invalid attendee id: %v", err)
return errs.NewValidationError(errs.SubtypeInvalidArgument, "invalid attendee id: %v", err)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Avoid wrapping typed validation errors.

Line 219 wraps the typed *errs.ValidationError returned by parseAttendees (line 64) in a new validation error, which loses the original error's typed structure and creates redundant message nesting ("invalid attendee id: unsupported attendee id format: X").

Return the error directly instead:

 attendees, err := parseAttendees(attendeesStr, currentUserId)
 if err != nil {
-    return errs.NewValidationError(errs.SubtypeInvalidArgument, "invalid attendee id: %v", err)
+    return err
 }

If parameter context is needed, add .WithParam("--attendee-ids") via type assertion or modify parseAttendees to accept the parameter name (see suggestion on lines 39-68).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
attendees, err := parseAttendees(attendeesStr, currentUserId)
if err != nil {
return output.ErrValidation("invalid attendee id: %v", err)
return errs.NewValidationError(errs.SubtypeInvalidArgument, "invalid attendee id: %v", err)
}
attendees, err := parseAttendees(attendeesStr, currentUserId)
if err != nil {
return err
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shortcuts/calendar/calendar_create.go` around lines 217 - 220, The code
currently wraps the typed *errs.ValidationError returned by
parseAttendees(attendeesStr, currentUserId) into a new errs.NewValidationError,
losing the original error type and nesting messages; instead, return the
parseAttendees error directly, and if you need parameter context call
WithParam("--attendee-ids") on the returned error via a type assertion (e.g., if
ve, ok := err.(*errs.ValidationError); ok { return
ve.WithParam("--attendee-ids") } else { return err }), or modify parseAttendees
to accept the parameter name so it can produce a validation error with the param
already set.

Comment on lines 327 to 330
attendees, err := parseAttendees(addStr, "")
if err != nil {
return output.ErrValidation("invalid attendee id: %v", err)
return errs.NewValidationError(errs.SubtypeInvalidArgument, "invalid attendee id: %v", err)
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Avoid wrapping typed validation errors.

Line 329 wraps the typed *errs.ValidationError returned by parseAttendees (calendar_create.go line 64) in a new validation error, which loses the original error's typed structure. Return the error directly:

 attendees, err := parseAttendees(addStr, "")
 if err != nil {
-    return errs.NewValidationError(errs.SubtypeInvalidArgument, "invalid attendee id: %v", err)
+    return err
 }

If parameter context is needed, add .WithParam("--add-attendee-ids") via type assertion or modify parseAttendees to accept the parameter name (see suggestion in calendar_create.go lines 39-68).

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
attendees, err := parseAttendees(addStr, "")
if err != nil {
return output.ErrValidation("invalid attendee id: %v", err)
return errs.NewValidationError(errs.SubtypeInvalidArgument, "invalid attendee id: %v", err)
}
attendees, err := parseAttendees(addStr, "")
if err != nil {
return err
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@shortcuts/calendar/calendar_update.go` around lines 327 - 330, The code in
calendar_update.go is wrapping the typed *errs.ValidationError from
parseAttendees into a new errs.NewValidationError which loses the original type;
change this to return the original error directly (return err) or, if you need
parameter context, type-assert err to *errs.ValidationError and call
.WithParam("--add-attendee-ids") before returning, or alternatively update
parseAttendees to accept a parameterName and set the param there; specifically
modify the block around parseAttendees(addStr, "") to avoid creating a new
ValidationError and preserve the original error type.

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

Labels

domain/calendar PR touches the calendar domain feature size/M Single-domain feat or fix with limited business impact

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant