{"record":{"id":"bdac1ea23f4c24c4","repo":"Tencent/WeKnora","slug":"failed-to-set-faq-metadata-w","errorCode":null,"errorMessage":"failed to set FAQ metadata: %w","messagePattern":"failed to set FAQ metadata: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/application/service/knowledge_faq.go","lineNumber":224,"sourceCode":"\tchunk := &types.Chunk{\n\t\tID:              uuid.New().String(),\n\t\tTenantID:        tenantID,\n\t\tKnowledgeID:     faqKnowledge.ID,\n\t\tKnowledgeBaseID: kb.ID,\n\t\tContent:         buildFAQChunkContent(meta, indexMode),\n\t\tIsEnabled:       isEnabled,\n\t\tFlags:           flags,\n\t\tChunkType:       types.ChunkTypeFAQ,\n\t\tTagID:           tagID, // 使用解析后的 TagID\n\t\tStatus:          int(types.ChunkStatusStored),\n\t}\n\t// 如果指定了 ID（用于数据迁移），设置 SeqID\n\tif payload.ID != nil && *payload.ID > 0 {\n\t\tchunk.SeqID = *payload.ID\n\t}\n\n\tif err := chunk.SetFAQMetadata(meta); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to set FAQ metadata: %w\", err)\n\t}\n\n\t// 保存chunk\n\tif err := s.chunkService.CreateChunks(ctx, []*types.Chunk{chunk}); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to create chunk: %w\", err)\n\t}\n\n\t// 索引chunk：交互式创建给索引步骤设硬上限，避免 embedding 抖动把请求拖长\n\tindexCtx, cancelIndex := context.WithTimeout(ctx, faqCreateIndexBudget)\n\tindexErr := s.indexFAQChunks(indexCtx, kb, faqKnowledge, []*types.Chunk{chunk}, embeddingModel, true, false)\n\tcancelIndex()\n\tif indexErr != nil {\n\t\t// 如果索引失败，删除已创建的chunk。回滚失败会留下一条 stored 状态的\n\t\t// 残留：它不出现在列表里，却会被重复校验命中，因此必须告警而非静默。\n\t\tif delErr := s.chunkService.DeleteChunk(ctx, chunk.ID); delErr != nil {\n\t\t\tlogger.Errorf(ctx,\n\t\t\t\t\"CreateFAQEntry: rollback failed, chunk %s left in stored state: %v\", chunk.ID, delErr)\n\t\t}","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/Tencent/WeKnora/blob/988cbb03305e055d8ebb7d46d9ac6cc0803cd074/internal/application/service/knowledge_faq.go#L206-L242","documentation":"CreateFAQEntry wraps errors from Chunk.SetFAQMetadata (internal/types/faq.go), which sanitizes the FAQ metadata and JSON-marshals it into the chunk, also computing a normalized ContentHash. This only fails when the FAQChunkMetadata cannot be JSON-encoded (e.g. unsupported field types), since nil handling is graceful. It means the FAQ payload could not be serialized into the chunk's Metadata column.","triggerScenarios":"A FAQChunkMetadata containing values that fail json.Marshal (e.g. channels, funcs, or cyclic/invalid structures introduced programmatically, typically via migration/import code paths constructing metadata manually) passed into CreateFAQEntry's internal meta.","commonSituations":"Custom import/migration tooling building FAQChunkMetadata with non-marshalable fields; a version change to FAQChunkMetadata adding an unsupported type; corrupt payloads crafted by API callers that survive sanitization but break marshaling.","solutions":["Inspect the wrapped json.Marshal error to find the offending field in FAQChunkMetadata.","Validate that the FAQ payload contains only strings/numbers/bools for metadata fields before submission.","Update or fix any custom import/migration code that constructs FAQChunkMetadata with non-JSON-serializable values.","Ensure client SDK / API version matches the server's FAQChunkMetadata schema."],"exampleFix":"// before\nmeta.Answer = someFuncRef // non-marshalable\nchunk.SetFAQMetadata(meta)\n// after\nmeta.Answer = \"plain text answer\"\nif err := chunk.SetFAQMetadata(meta); err != nil {\n\treturn nil, fmt.Errorf(\"invalid FAQ payload: %w\", err)\n}","handlingStrategy":"validation","validationCode":"// ensure payload fields are JSON-safe before calling the API\nfor _, q := range append(payload.SimilarQuestions, payload.OriginQuestion, payload.Answer) {\n\tif strings.ContainsAny(q, \"\\x00\") {\n\t\treturn errors.New(\"FAQ payload contains non-text control bytes\")\n\t}\n}\nif _, err := json.Marshal(payload); err != nil {\n\treturn fmt.Errorf(\"payload not serializable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"entry, err := svc.CreateFAQEntry(ctx, kbID, payload)\nif err != nil && strings.Contains(err.Error(), \"failed to set FAQ metadata\") {\n\treturn nil, fmt.Errorf(\"FAQ payload cannot be stored as metadata; check for non-JSON-serializable fields: %w\", err)\n}","preventionTips":["Keep FAQChunkMetadata fields limited to JSON-native types","Sanitize caller input for control characters before submission","Keep import/migration tooling in sync with the FAQChunkMetadata schema","Pin client SDK version to the server's FAQ metadata schema version"],"tags":["json","serialization","faq","go"],"backgroundTag":"json-marshal-failed","analyzedSha":"988cbb03305e055d8ebb7d46d9ac6cc0803cd074","analyzedAt":"2026-09-02T14:41:08.344Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}