m1k1o/neko · error · ErrBackendRespone
error response from backend
Error message
error response from backend
What it means
ErrBackendRespone (sic) is the sentinel error signaling that the legacy proxy's backend HTTP request returned a non-success status code. It is returned by session.req (via apiReq) and wrapped with the backend's JSON message or a raw body, so callers should use errors.Is to detect backend rejection regardless of formatting. The misspelling is part of the public API and must be matched exactly.
Source
Thrown at server/internal/http/legacy/session.go:24
"fmt"
"io"
"net/http"
"path"
"strings"
"sync"
oldTypes "github.com/m1k1o/neko/server/internal/http/legacy/types"
"github.com/m1k1o/neko/server/internal/api"
"github.com/m1k1o/neko/server/pkg/types"
"github.com/gorilla/websocket"
"github.com/rs/zerolog"
)
var (
ErrWebsocketSend = fmt.Errorf("failed to send message to websocket")
ErrBackendRespone = fmt.Errorf("error response from backend")
)
type memberStruct struct {
member *oldTypes.Member
connected bool
sent bool
}
type session struct {
r *http.Request
h *LegacyHandler
logger zerolog.Logger
serverAddr string
pathPrefix string
id, ip string
token stringView on GitHub (pinned to b0f01cedea)
Solutions
- Inspect the wrapped message (fmt.Errorf %s) and the backend logs to find the actual status code and cause.
- Use errors.Is(err, ErrBackendRespone) to branch on backend rejection vs other failures.
- Verify backend URL, credentials/token, and API compatibility with the running backend version.
- Add retry with backoff for transient 5xx responses in apiReq callers.
Example fix
// before
if err := s.apiReq(http.MethodGet, "/api/sessions", nil, &sessions); err != nil {
return err
}
// after
if err := s.apiReq(http.MethodGet, "/api/sessions", nil, &sessions); err != nil {
if errors.Is(err, ErrBackendRespone) {
return fmt.Errorf("backend rejected sessions fetch: %w", err)
}
return err
} Defensive patterns
Strategy: try-catch
Validate before calling
resp, err := http.Head(backendURL + "/api/stats")
if err != nil || resp.StatusCode >= 400 {
return fmt.Errorf("backend not healthy before calling apiReq: status %v", resp.StatusCode)
} Type guard
func isBackendResponseError(err error) bool {
return errors.Is(err, ErrBackendRespone)
} Try / catch
if err := s.apiReq(method, path, req, &out); err != nil {
if errors.Is(err, ErrBackendRespone) {
// backend rejected: log wrapped message, maybe re-auth
return fmt.Errorf("backend error: %w", err)
}
return err
} Prevention
- Always match with errors.Is, never string comparison on the message.
- Keep the backend URL/auth configuration validated at startup.
- Monitor backend health and alert on rising non-2xx rates.
- Pin compatible proxy/backend versions to avoid API drift.
When it happens
Trigger: Any session.apiReq call (e.g. GET /api/sessions, /api/stats, /api/room/settings from Route, or create/destroy) where the backend responds with a non-2xx status and the body parses as JSON with a 'message' field.
Common situations: Backend restarted or upgrading (502/503); wrong backend URL/port configured; auth token expired causing 401/403; rate limiting on the backend; version mismatch between proxy and backend API routes.
Related errors
AI-assisted analysis of m1k1o/neko@b0f01cedea (2026-09-01).
Data as JSON: /api/errors/8546a397d4267c39.
Report an issue: GitHub.