larksuite/cli · error
objective %s: %w
Error message
objective %s: %w
What it means
During rollback after a failed OKR batch create, each per-objective deletion failure is wrapped as `objective %s: %w`, preserving the delete error and the objective ID. These wraps are collected into an errors list and later assembled into a typed rollback error by buildRollbackError, so the user knows which objectives could not be cleaned up.
Source
Thrown at shortcuts/okr/okr_batch_create.go:170
if err != nil {
return wrapOkrNetworkErr(err, "failed to delete objective %s during rollback", objectiveID)
}
return nil
}
// rollback deletes created objectives in reverse order.
// KRs are automatically deleted by the backend when the objective is deleted.
func rollback(ctx context.Context, runtime *common.RuntimeContext, created []createdObjective) []error {
var errsList []error
// Iterate in reverse order
for i := len(created) - 1; i >= 0; i-- {
obj := created[i]
// Delete the objective (backend automatically deletes its KRs)
if err := deleteObjective(ctx, runtime, obj.ObjectiveID); err != nil {
//nolint:forbidigo // intermediate wrap for rollback error collection; final error is typed via buildRollbackError
errsList = append(errsList, fmt.Errorf("objective %s: %w", obj.ObjectiveID, err))
}
// Rate limiting between deletions
if i > 0 {
time.Sleep(500 * time.Millisecond)
}
}
return errsList
}
// OKRBatchCreate batch creates objectives and their key results.
var OKRBatchCreate = common.Shortcut{
Service: "okr",
Command: "+batch-create",
Description: "Batch create OKR objectives and key results with rollback on failure",
Risk: "write",
Scopes: []string{"okr:okr.content:writeonly"},View on GitHub (pinned to 7fd6ef3c07)
Solutions
- Read the wrapped cause for the listed objective ID and fix the underlying delete failure (permissions, scopes, rate limits).
- Manually delete the leftover objective IDs reported by the rollback error via the OKR delete command.
- Retry the operation after resolving the cause; rollback errors indicate leftover state, not a problem with your input.
Defensive patterns
Strategy: try-catch
Try / catch
err := batchCreate(ctx, runtime, objectives)
if err != nil {
var rb *errs.TypedError
if errors.As(err, &rb) && strings.Contains(err.Error(), "objective") {
// parse leftover objective IDs from the wrapped message and delete them manually
for _, id := range extractObjectiveIDs(err.Error()) {
_ = deleteObjective(ctx, runtime, id)
}
}
} Prevention
- Ensure the token has both create and delete scopes for OKR before batch runs.
- Avoid concurrent mutations of the same OKR space during batch operations.
- Handle partial-failure reports promptly to avoid orphaned objectives.
When it happens
Trigger: A batch OKR create partially succeeded, rollback began, and deleteObjective failed for a specific objective ID — e.g. the objective was already deleted, permissions were revoked, or a rate limit hit that specific call.
Common situations: Partial batch failures where some objectives were created before the batch aborted; concurrent edits removed the objective mid-rollback; transient API outages or permission-scoped tokens that can create but not delete.
AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04).
Data as JSON: /api/errors/7bc3f36d5e72188e.
Report an issue: GitHub.