Skip to content

Occurrence URLs make commands act on the whole recurring series #947

Closed

Description

@robzolkos

Found by Codex while reviewing #946.

Symptom

basecamp schedule update https://3.basecamp.com/123/buckets/456/schedule_entries/789/occurrences/20261022/edit --summary X updates entry 789. That changes every occurrence of the recurring event, not the one the URL names (schedule.go:642 calls extractWithProject, then UpdateEntry).

Root cause

The shared ID helpers extractID and extractWithProject ([helpers.go:561
580](

func extractID(arg string) string {

580), helpers.go:569) and the urlarg.Extract* functions behind them return only a recording ID and a project ID. They drop OccurrenceDate without saying so. About 75 call sites in internal/commands use them. Only show, schedule show and spotlight read OccurrenceDate; they call urlarg.Parse directly. Every other command that changes something and is given an occurrence URL acts on the whole series: schedule update, recordings trash|archive|restore, comments, boosts, subscriptions and others. An occurrence is its own recording in bc3, so acting on the series is the wrong item.

The API cannot change a single occurrence

bc3's API exposes only GET /schedule_entries/:id/occurrences/:date. Updating, trashing and archiving one occurrence are web-only routes. The SDK has only GetEntryOccurrence. So the CLI cannot support changing one occurrence, and refusing the URL is the correct behavior, not a stopgap.

Fix

Refuse an occurrence URL in the shared ID helpers, with a hint to pass the entry's ID to act on the series. Commands that genuinely handle occurrences (show, schedule show) keep parsing the URL themselves. That covers every call site at once, instead of each command checking.

Activity

  1. changed the title [-]schedule update with an occurrence URL edits the whole series[/-] [+]Occurrence URLs make commands act on the whole recurring series[/+] on Oct 23, 2026
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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions