vxcontrol/pentagi · error

knowledge: marshal cmetadata: %w

Error message

knowledge: marshal cmetadata: %w

What it means

CreateDocument serializes the knowledgeMeta struct to JSON for the cmetadata column via metaToJSON. This should only fail for unsupported field values (e.g. non-marshalable types if meta is extended), and the error is wrapped as 'knowledge: marshal cmetadata'.

Source

Thrown at backend/pkg/database/knowledge/knowledge.go:505

	meta.PartSize = len(content)
	meta.TotalSize = len(content)

	// Truncate to embedding size limit for vector computation; full content goes to DB.
	embeddingText := content
	if len(embeddingText) > ks.maxEmbeddingBytes {
		embeddingText = embeddingText[:ks.maxEmbeddingBytes]
	}
	vecs, err := ks.embedder.EmbedDocuments(ctx, []string{embeddingText})
	if err != nil {
		return nil, fmt.Errorf("knowledge: compute embedding: %w", err)
	}
	if len(vecs) == 0 {
		return nil, fmt.Errorf("knowledge: embedder returned no vectors")
	}

	cmJSON, err := metaToJSON(meta)
	if err != nil {
		return nil, fmt.Errorf("knowledge: marshal cmetadata: %w", err)
	}

	id := uuid.New()
	docID, err := ks.db.InsertKnowledgeDocument(ctx, database.InsertKnowledgeDocumentParams{
		Uuid:      id,
		Document:  nsOf(content),
		Embedding: formatVector(vecs[0]),
		Cmetadata: cmJSON.RawMessage,
	})
	if err != nil {
		return nil, fmt.Errorf("knowledge: create document: %w", err)
	}

	doc := metaToModelDoc(docID, content, meta)
	ks.newKnp(userID).KnowledgeDocumentCreated(ctx, doc)
	return doc, nil
}

View on GitHub (pinned to ea665308ba)

Solutions

  1. Inspect the wrapped json error; it names the offending field/type.
  2. Ensure all cmetadata values are JSON-safe primitives (string, number, bool, nil).
  3. Add a unit test for metaToJSON with the new metadata shape before extending knowledgeMeta.
  4. If using a map-based metadata path, sanitize/convert values with a normalization step before marshaling.

Example fix

// before
cmJSON, err := metaToJSON(meta) // fails on unmarshalable value
// after
safe := make(map[string]any, len(meta))
for k, v := range meta {
    switch v.(type) {
    case string, bool, float64, int64, nil:
        safe[k] = v
    default:
        safe[k] = fmt.Sprintf("%v", v)
    }
}
cmJSON, err := metaToJSON(safe)
Defensive patterns

Strategy: validation

Validate before calling

if _, err := json.Marshal(meta); err != nil {
    return nil, fmt.Errorf("invalid metadata: %w", err)
}

Type guard

func isJSONMarshalErr(err error) bool {
    var je *json.UnsupportedTypeError
    var nfe *json.UnsupportedValueError
    return errors.As(err, &je) || errors.As(err, &nfe)
}

Try / catch

doc, err := store.CreateDocument(ctx, userID, input)
if err != nil {
    if isJSONMarshalErr(err) {
        return fmt.Errorf("metadata contains unsupported values: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: metaToJSON returning an error — practically only when the metadata contains values json.Marshal cannot handle (channels, funcs, cyclic references) after custom extensions to knowledgeMeta or callers injecting raw metadata.

Common situations: A developer extends cmetadata with a custom type lacking JSON marshaling; passing a map containing NaN/Inf floats or nested unmarshalable values.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/53c999d7f374aacc. Report an issue: GitHub.