gofiber/fiber · error · ErrCursorEncode
paginate: failed to encode cursor values
Error message
paginate: failed to encode cursor values
What it means
Returned by paginate.PageInfo.SetNextCursor (page_info.go:15, 212, 217) when the cursor values map cannot be JSON-marshaled, or when the resulting base64 cursor exceeds maxCursorLen. SetNextCursor serializes the provided map[string]any to JSON, base64-encodes it, and sets NextCursor/HasMore. A marshaling error (e.g. a value containing a channel, func, or a recursive struct) or an oversized cursor triggers this wrapped error.
Source
Thrown at middleware/paginate/page_info.go:15
package paginate
import (
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"net/url"
"slices"
"github.com/gofiber/utils/v2"
)
// ErrCursorEncode is returned when cursor values cannot be encoded.
var ErrCursorEncode = errors.New("paginate: failed to encode cursor values")
// SortOrder represents sort order.
type SortOrder string
const (
ASC SortOrder = "asc"
DESC SortOrder = "desc"
)
// SortField represents a sort field with direction.
type SortField struct {
Field string `json:"field"`
Order SortOrder `json:"order"`
}
// SortOrderFromString returns a SortOrder from a string (case-insensitive).
func SortOrderFromString(s string) SortOrder {
if utils.EqualFold(s, "desc") {View on GitHub (pinned to 9a4c7e57fe)
Solutions
- Keep cursor values minimal — store only the sort key(s) and offset/ID needed to resume, not full objects.
- Ensure all values in the cursor map are JSON-serializable (strings, numbers, bools, simple structs).
- If you need complex state, store it server-side keyed by a short cursor ID and put only the ID in the cursor.
Example fix
// before — un-serializable / oversized cursor
pageInfo.SetNextCursor(map[string]any{
"lastItem": largeObject,
"filter": func() string { return "..." },
})
// after — minimal, serializable cursor
pageInfo.SetNextCursor(map[string]any{
"id": lastID,
"ts": lastTimestamp.Unix(),
}) Defensive patterns
Strategy: validation
Validate before calling
// Validate cursor values are serializable before encoding
for k, v := range cursorValues {
switch v.(type) {
case func(), chan struct{}:
return fmt.Errorf("cursor value %q is not serializable", k)
}
} Try / catch
// Handle encode failure gracefully in your handler
if err := pageInfo.SetNextCursor(values); err != nil {
log.Printf("cursor encode failed: %v", err)
// proceed without a cursor; client gets no next page
} Prevention
- Store only primitive serializable values (string, int, float) in cursors.
- Keep cursors minimal — just the sort key and offset.
- Store complex state server-side and reference it by a short ID in the cursor.
When it happens
Trigger: Calling pageInfo.SetNextCursor(map) with a value that json.Marshal cannot handle (functions, channels, cyclic references), or with a very large map whose encoded form exceeds the internal maxCursorLen constant. This happens in handler code building pagination responses.
Common situations: Storing un-serializable types (time.Duration as a func, channels) in cursor values; embedding large objects or binary blobs in the cursor instead of just an ID/offset; cursor values growing unbounded (e.g. accumulating filter state).
Related errors
- ErrCursorEncode
- sse: marshal data: %w
- fiber: failed to encode shared state %s value: %w
- cache: failed to unmarshal key %q: %w
- cache: failed to marshal key %q: %w
AI-assisted analysis of gofiber/fiber@9a4c7e57fe (2026-08-04).
Data as JSON: /data/errors/933962d255ef70be.json.
Report an issue: GitHub.