Billionmail/BillionMail · error

error unmarshalling knowledge base: %v

Error message

error unmarshalling knowledge base: %v

What it means

After a successful read, ReadKnowledgeBase unmarshals the bytes into a KnowledgeInfo struct. Malformed or schema-incompatible JSON yields 'error unmarshalling knowledge base: %v' with the encoding/json cause. The file exists and was readable, but its contents cannot be represented as KnowledgeInfo.

Source

Thrown at core/internal/service/askai/project.go:302

	return nil
}

// ReadKnowledgeBase reads a specific knowledge base from a JSON file based on the provided domain and knowledge ID.
// It returns a KnowledgeInfo struct or an error if the file does not exist or cannot be
func ReadKnowledgeBase(Domain string, Kid string) (KnowledgeInfo, error) {
	filename := fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/knowledge/%s.json", Domain, Kid)
	if !public.FileExists(filename) {
		return KnowledgeInfo{}, fmt.Errorf("knowledge base file does not exist: %s", filename)
	}
	data, err := os.ReadFile(filename)
	if err != nil {
		return KnowledgeInfo{}, fmt.Errorf("error reading knowledge base file: %v", err)
	}

	var knowledge KnowledgeInfo
	err = json.Unmarshal(data, &knowledge)
	if err != nil {
		return KnowledgeInfo{}, fmt.Errorf("error unmarshalling knowledge base: %v", err)
	}
	return knowledge, nil
}

// SaveKnowledgeBase saves the provided KnowledgeInfo to a JSON file based on the domain and knowledge ID.
// It creates the directory if it does not exist and writes the knowledge information to a JSON file
func SaveKnowledgeBase(Domain string, knowledge KnowledgeInfo) error {
	knowledgePath := fmt.Sprintf("%s/%s/knowledge", PRODUCT_CONFIG_PATH, Domain)
	if !public.FileExists(knowledgePath) {
		os.MkdirAll(knowledgePath, os.ModePerm)
	}
	filename := fmt.Sprintf("%s/%s.json", knowledgePath, knowledge.Kid)

	configStr, err := json.MarshalIndent(knowledge, "", "  ")
	if err != nil {
		return fmt.Errorf("error marshalling knowledge base: %v", err)
	}

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Validate the file with jq (or json.Unmarshal in a scratch test) to see the exact syntax/type error
  2. Compare file contents against the current KnowledgeInfo struct field types
  3. Re-save the knowledge entry (or delete it) via SaveKnowledgeBase to regenerate valid JSON
  4. Make saves atomic (write temp file + os.Rename) to prevent truncation
  5. Inspect the wrapped json error (offset/type mismatch) to locate the bad field

Example fix

// before
kb, err := askai.ReadKnowledgeBase(domain, kid)
// after
kb, err := askai.ReadKnowledgeBase(domain, kid)
if err != nil && strings.Contains(err.Error(), "unmarshalling") {
    os.Remove(fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/knowledge/%s.json", domain, kid))
    return fmt.Errorf("corrupt knowledge %s removed: %w", kid, err)
}
Defensive patterns

Strategy: validation

Validate before calling

data, err := os.ReadFile(fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/knowledge/%s.json", domain, kid))
if err != nil { return err }
var probe askai.KnowledgeInfo
if err := json.Unmarshal(data, &probe); err != nil {
    return fmt.Errorf("corrupt knowledge file: %w", err)
}

Type guard

func validKnowledgeJSON(data []byte) bool {
    var k askai.KnowledgeInfo
    return json.Unmarshal(data, &k) == nil
}

Try / catch

kb, err := askai.ReadKnowledgeBase(domain, kid)
if err != nil && strings.Contains(err.Error(), "unmarshalling knowledge base") {
    log.Printf("corrupt knowledge %s/%s: %v", domain, kid, err)
    return respondConflict("knowledge entry is corrupt; re-save it")
}

Prevention

When it happens

Trigger: ReadKnowledgeBase(Domain, Kid) where the JSON file exists and reads fine but json.Unmarshal fails: truncated file, invalid syntax, or fields with wrong types (e.g. string where KnowledgeInfo expects a number/array).

Common situations: Partial write from a crashed SaveKnowledgeBase (no atomic rename); manual editing that broke JSON syntax; KnowledgeInfo struct fields changed in a code update so old files no longer decode; non-JSON content saved under a .json name.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/8ab25ac07e23ba1d. Report an issue: GitHub.