{"record":{"id":"1cbf66456df0c010","repo":"Tencent/WeKnora","slug":"marshal-optionalpayload-w","errorCode":null,"errorMessage":"marshal optionalPayload: %w","messagePattern":"marshal optionalPayload: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/infrastructure/docparser/paddleocr_vl_cloud_converter.go","lineNumber":113,"sourceCode":"func (c *PaddleOCRVLCloudReader) optionalPayload() map[string]interface{} {\n\t// Shared with the self-hosted engine so both produce identical output.\n\treturn paddleOCRVLRecognitionParams(c.useSeal, c.useChart)\n}\n\n// --- job submit ---\n\ntype paddleOCRVLCloudSubmitResponse struct {\n\tData struct {\n\t\tJobID string `json:\"jobId\"`\n\t} `json:\"data\"`\n\tErrorCode int    `json:\"errorCode\"`\n\tErrorMsg  string `json:\"errorMsg\"`\n}\n\nfunc (c *PaddleOCRVLCloudReader) submitJob(ctx context.Context, req *types.ReadRequest, content []byte) (string, error) {\n\toptional, err := json.Marshal(c.optionalPayload())\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"marshal optionalPayload: %w\", err)\n\t}\n\n\tfileName := req.FileName\n\tif fileName == \"\" {\n\t\text := strings.TrimPrefix(req.FileType, \".\")\n\t\tif ext == \"\" {\n\t\t\text = \"pdf\"\n\t\t}\n\t\tfileName = \"document.\" + ext\n\t}\n\n\tvar body bytes.Buffer\n\twriter := multipart.NewWriter(&body)\n\t_ = writer.WriteField(\"model\", c.model)\n\t_ = writer.WriteField(\"optionalPayload\", string(optional))\n\tpart, err := writer.CreateFormFile(\"file\", filepath.Base(fileName))\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"create form file: %w\", err)","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/infrastructure/docparser/paddleocr_vl_cloud_converter.go#L95-L131","documentation":"submitJob marshals the converter's optionalPayload (extra model options sent as the optionalPayload form field) with encoding/json before building the multipart request. Since the payload is composed of plain Go values, this should never fail in practice; if it does, it signals a payload containing a value json.Marshal cannot encode (e.g. a channel, func, or cyclic structure) introduced by a code change.","triggerScenarios":"Read -> submitJob -> json.Marshal(c.optionalPayload()) returns an error — only possible when optionalPayload is extended with unsupported types (chan, func, unencodable cyclic data).","commonSituations":"A recent code change added a custom option value (e.g. a struct with a func or chan field) to optionalPayload; unsupported-type JSON fields added without json tags or marshaling support.","solutions":["Check the wrapped error for 'json: unsupported type: ...' and fix the offending field type","Ensure all optionalPayload fields are JSON-encodable primitives, slices, maps, or tagged structs","Add a unit test marshaling optionalPayload to catch regressions","If a dynamic option must carry non-encodable data, convert it to a string/encodable representation first"],"exampleFix":"// before\nOptions map[string]any // may hold unsupported values\n// after\nfunc (c *PaddleOCRVLCloudReader) optionalPayload() map[string]any {\n\treturn map[string]any{\"model\": c.model, \"language\": c.language} // encodable fields only\n}","handlingStrategy":"validation","validationCode":"if _, err := json.Marshal(c.optionalPayload()); err != nil {\n    return fmt.Errorf(\"optionalPayload not encodable: %w\", err)\n}","typeGuard":"func optionalPayloadEncodable(p map[string]any) bool {\n    _, err := json.Marshal(p)\n    return err == nil\n}","tryCatchPattern":"out, err := reader.Read(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"marshal optionalPayload\") {\n    // developer bug: fix the payload type, not a runtime retry\n    return fmt.Errorf(\"config bug in optionalPayload: %w\", err)\n}","preventionTips":["Keep optionalPayload limited to JSON-native types with explicit tags","Add a unit test that marshals optionalPayload for every config path","Never put chan/func/cyclic values into the payload map","Review optionalPayload changes in code review for encodability"],"tags":["json","marshal","paddleocr","docparser"],"backgroundTag":"json-marshal-unsupported-type","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}