Billionmail/BillionMail · error

error marshalling site map: %v

Error message

error marshalling site map: %v

What it means

SaveSiteMap marshals a []SiteMap with json.MarshalIndent before writing sitemap.json. This error wraps a marshalling failure. Like the other marshal errors here, it cannot fire with the current plain-struct SiteMap; it requires unmarshalable values (chan, func, cyclic pointers) in the slice.

Source

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

	}
	data, err := os.ReadFile(filename)
	if err != nil {
		return nil, fmt.Errorf("error reading site map file: %v", err)
	}

	var siteMap []SiteMap
	err = json.Unmarshal(data, &siteMap)
	if err != nil {
		return nil, fmt.Errorf("error unmarshalling site map: %v", err)
	}
	return siteMap, nil
}

func SaveSiteMap(Domain string, siteMap []SiteMap) error {
	filename := fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/sitemap.json", Domain)
	data, err := json.MarshalIndent(siteMap, "", "  ")
	if err != nil {
		return fmt.Errorf("error marshalling site map: %v", err)
	}
	err = os.WriteFile(filename, data, 0644)
	if err != nil {
		return fmt.Errorf("error saving site map file: %v", err)
	}
	return nil
}

// AddSiteMapNode adds a new site map node with the provided title and URI path to the site map of the specified domain.
// It reads the existing site map, appends the new node, and saves the updated site map back to the file.
// If the site map file does not exist or cannot be read, it returns an error.
func AddSiteMapNode(Domain string, Title string, UriPath string) error {
	siteMap, err := GetSiteMap(Domain)
	if err != nil {
		return fmt.Errorf("error getting site map: %v", err)
	}

	newNode := SiteMap{

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Read the wrapped message ('json: unsupported type: ...') to identify the offending SiteMap field.
  2. Replace the unmarshalable field with a serializable equivalent (string key, plain struct, JSON tag adjustments).
  3. Implement a custom json.Marshaler only if the field genuinely needs derived output, and guarantee it emits valid JSON.

Example fix

// before
type SiteMap struct {
    Loader func() error // unsupported by encoding/json
}
// after
type SiteMap struct {
    LoaderName string // store an identifier instead of a func
}
Defensive patterns

Strategy: validation

Validate before calling

// Build-time sentinel: fails fast if SiteMap ever becomes unmarshalable
var _ = func() bool {
    if _, err := json.Marshal([]SiteMap{{Title: "t", UriPath: "/"}}); err != nil {
        panic("SiteMap not JSON-marshalable: " + err.Error())
    }
    return true
}()

Type guard

func isMarshalableSiteMap(m []SiteMap) bool {
    _, err := json.Marshal(m)
    return err == nil
}

Try / catch

if err := SaveSiteMap(domain, siteMap); err != nil {
    var ut *json.UnsupportedTypeError
    if errors.As(err, &ut) { log.Printf("unmarshalable field %s", ut.Type) }
    return err
}

Prevention

When it happens

Trigger: Calling SaveSiteMap (directly or via AppendSitemap) with a []SiteMap containing an element with an unsupported field type, or a slice built from a cyclic data structure.

Common situations: Encountered by developers extending SiteMap with non-JSON-serializable fields, or in tests injecting mocks with channels/functions into nodes.

Related errors


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