Files
kandev/apps/backend/internal/sprites/errors.go
T
José Almeida 85885dd866 feat(sprites): provision a fresh sandbox when the persisted one is gone
Resuming a Sprites task whose sandbox was destroyed upstream returned
"sprite not found" and dead-ended the user. Detect the upstream 404 via
a typed ErrSpriteNotFound sentinel, mark the reconnect step skipped with
a user-facing warning explaining what happened, swap the prepare plan
in place to the fresh-provision shape, and continue the launch under a
new sandbox name on the same branch.

The progress plan is now mutable so the reporter can stream the fresh
steps live after the reconnect-then-fresh transition. Only the explicit
not-found case triggers fallback; other reconnect failures still
surface as before, and the fallback fires at most once per launch.
2026-05-05 21:19:39 +01:00

49 lines
1.4 KiB
Go

package sprites
import (
"errors"
"fmt"
"strings"
)
// ErrSpriteNotFound is returned when an upstream Sprites API call indicates the
// sandbox does not exist. The upstream SDK currently returns plain errors with
// a "sprite not found: <name>" message for 404 responses; this sentinel lets
// callers branch on that case without ad-hoc string matching.
var ErrSpriteNotFound = errors.New("sprite not found")
// WrapNotFound wraps err with ErrSpriteNotFound when err looks like an upstream
// "sprite not found" / 404 response. Other errors are returned unchanged. Pass
// the returned error to errors.Is(err, ErrSpriteNotFound) to detect the case.
func WrapNotFound(err error) error {
if err == nil {
return nil
}
if errors.Is(err, ErrSpriteNotFound) {
return err
}
if !looksLikeNotFound(err.Error()) {
return err
}
return fmt.Errorf("%w: %w", ErrSpriteNotFound, err)
}
// IsNotFound reports whether err originated from an upstream "not found"
// response, even when WrapNotFound has not been applied. Useful for callers
// that receive a raw upstream error.
func IsNotFound(err error) bool {
if err == nil {
return false
}
if errors.Is(err, ErrSpriteNotFound) {
return true
}
return looksLikeNotFound(err.Error())
}
func looksLikeNotFound(msg string) bool {
lower := strings.ToLower(msg)
return strings.Contains(lower, "sprite not found") ||
strings.Contains(lower, "not found")
}