{"record":{"id":"b1fe5297dbd0adab","repo":"gofiber/fiber","slug":"w-w-b1fe52","errorCode":null,"errorMessage":"%w: %w","messagePattern":"%w: %w","errorType":"exception","errorClass":"ErrCursorEncode","httpStatus":null,"severity":"error","filePath":"middleware/paginate/page_info.go","lineNumber":212,"sourceCode":"\tif err := unmarshal(data, &values); err != nil {\n\t\treturn nil\n\t}\n\n\tp.cursorData = values\n\n\treturn values\n}\n\n// SetNextCursor encodes a key-value map into an opaque cursor token\n// and sets both NextCursor and HasMore on the PageInfo.\nfunc (p *PageInfo) SetNextCursor(values map[string]any) error {\n\tmarshal := p.jsonMarshal\n\tif marshal == nil {\n\t\tmarshal = json.Marshal\n\t}\n\tdata, err := marshal(values)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"%w: %w\", ErrCursorEncode, err)\n\t}\n\n\tencoded := base64.RawURLEncoding.EncodeToString(data)\n\tif len(encoded) > maxCursorLen {\n\t\treturn fmt.Errorf(\"%w: cursor token exceeds maximum length (%d)\", ErrCursorEncode, maxCursorLen)\n\t}\n\n\tp.NextCursor = encoded\n\tp.HasMore = true\n\n\treturn nil\n}\n","sourceCodeStart":194,"sourceCodeEnd":225,"githubUrl":"https://github.com/gofiber/fiber/blob/a105acad6c1e4576a77f01e02973f67e962bb58d/middleware/paginate/page_info.go#L194-L225","documentation":"SetNextCursor marshals the values map with json.Marshal (or a custom jsonMarshal) and wraps any failure with the ErrCursorEncode sentinel. This is the only failure mode for the encode step other than length (error 186). The map's values must all be JSON-encodable.","triggerScenarios":"Passing a map containing a non-encodable Go type: chan, func, complex64/128, or a struct with an unexported field that json cannot reach. A cyclic structure via pointers/interfaces also triggers it. A custom jsonMarshal injected via the unexported field that itself errors.","commonSituations":"Cursor map built from request-derived data that includes a func or chan; storing a *big.Int or other type without a MarshalJSON method; building the map from interface{} values that occasionally hold an unsupported type at runtime.","solutions":["Log the wrapped error (it names the offending type, e.g. json: unsupported type: chan struct{}).","Coerce cursor values to JSON-safe primitives before calling SetNextCursor: string, int, float64, bool, time.Time (with format check), or a struct with exported fields only.","Add a type-check helper that walks the map and rejects/converts unsupported types before encoding.","If using a custom jsonMarshal (e.g. sonic), verify it accepts the same type set as encoding/json or pre-convert.","Unit-test SetNextCursor with the exact map shape produced by your handler."],"exampleFix":"// before: map carries an unsupported func\nvalues := map[string]any{\"id\": id, \"fn\": someFunc}\npi.SetNextCursor(values) // error\n\n// after: only JSON-safe scalars\nvalues := map[string]any{\"id\": id}\npi.SetNextCursor(values)","handlingStrategy":"validation","validationCode":"// Reject non-JSON-safe values before encoding.\nfunc safeCursorValues(m map[string]any) (map[string]any, error) {\n  for k, v := range m {\n    switch v.(type) {\n    case nil, bool, int, int64, float64, string, json.Marshaler:\n    default:\n      return nil, fmt.Errorf(\"cursor key %q has unsupported type %T\", k, v)\n    }\n  }\n  return m, nil\n}","typeGuard":"func isJSONSafe(v any) bool {\n  switch v.(type) {\n  case nil, bool, int, int32, int64, uint, uint32, uint64, float32, float64, string:\n    return true\n  }\n  if _, ok := v.(json.Marshaler); ok { return true }\n  return false\n}","tryCatchPattern":"if err := pi.SetNextCursor(values); err != nil {\n  if errors.Is(err, paginate.ErrCursorEncode) { /* log and omit cursor */ }\n}","preventionTips":["Build cursor maps only from primitives you control.","Unit-test SetNextCursor with the production map shape.","Log the wrapped error — it names the offending type."],"tags":["paginate","cursor","json","encoding"],"backgroundTag":null,"analyzedSha":"a105acad6c1e4576a77f01e02973f67e962bb58d","analyzedAt":"2026-08-11T17:33:26.942Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}