Billionmail/BillionMail · error

error unmarshalling images configuration: %v

Error message

error unmarshalling images configuration: %v

What it means

ReadImagesConfig returns this when the images.json file exists but json.Unmarshal cannot parse it into []ImageInfo. It means the persisted JSON is corrupted, truncated, or no longer matches the ImageInfo schema (e.g. a field changed type).

Source

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

		return fmt.Errorf("error saving images file: %v", err)
	}
	return nil
}

func ReadImagesConfig(Domain string) ([]ImageInfo, error) {
	imagesPath := fmt.Sprintf("%s/%s/images.json", PRODUCT_CONFIG_PATH, Domain)
	if !public.FileExists(imagesPath) {
		os.WriteFile(imagesPath, []byte("[]"), 0644)
	}
	data, err := os.ReadFile(imagesPath)
	if err != nil {
		return []ImageInfo{}, fmt.Errorf("error reading images configuration file: %v", err)
	}

	var images []ImageInfo
	err = json.Unmarshal(data, &images)
	if err != nil {
		return []ImageInfo{}, fmt.Errorf("error unmarshalling images configuration: %v", err)
	}
	return images, nil
}

type UploadImageResponse struct {
	Status bool   `json:"status"`
	Msg    string `json:"msg"`
	Data   struct {
		URL string `json:"url"`
	} `json:"data"`
}

// UploadImage(req.Domain, req.Image, req.Filename, req.AltText, req.ImageTag)
func UploadImage(Domain string, Image string, Filename string, AltText string, ImageTag string) (string, error) {
	imageInfo := ImageInfo{
		ImageId:    GetUUID(),
		ImageUrl:   "",
		Filename:   Filename,

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Inspect/validate images.json (jq . <path>) and repair or delete it so the code re-seeds '[]'.
  2. Write atomically (write temp file + rename) in SaveImagesConfig to prevent truncated files.
  3. Serialize writes to images.json with a file lock or single-writer goroutine.
  4. On unmarshal failure, back up the corrupt file and fall back to an empty slice with a warning if acceptable.

Example fix

// before
var images []ImageInfo
err = json.Unmarshal(data, &images)
if err != nil {
	return []ImageInfo{}, fmt.Errorf("error unmarshalling images configuration: %v", err)
}
// after
var images []ImageInfo
if err := json.Unmarshal(data, &images); err != nil {
	_ = os.Rename(imagesPath, imagesPath+".corrupt")
	return []ImageInfo{}, fmt.Errorf("error unmarshalling images configuration: %v", err)
}
Defensive patterns

Strategy: validation

Validate before calling

func validImagesJSON(path string) bool {
	data, err := os.ReadFile(path)
	if err != nil {
		return false
	}
	var v []ImageInfo
	return json.Unmarshal(data, &v) == nil
}
// if !validImagesJSON(imagesPath) { repair or reset before calling ReadImagesConfig }

Type guard

func isImageInfoSlice(b []byte) bool {
	var v []ImageInfo
	return len(b) > 0 && json.Unmarshal(b, &v) == nil
}

Try / catch

images, err := ReadImagesConfig(domain)
if err != nil && strings.Contains(err.Error(), "unmarshalling images configuration") {
	os.Rename(imagesPath, imagesPath+".corrupt")
	images = []ImageInfo{}
}

Prevention

When it happens

Trigger: Calling ReadImagesConfig when images.json contains malformed JSON (partial write from a concurrent save/crash), a different top-level shape (object instead of array), or fields whose types changed in a new ImageInfo version.

Common situations: Two processes writing images.json concurrently without locking, a crash mid-write producing a truncated file, manual edits to the file, or an upgrade that changed ImageInfo field types.

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/4e9e7df237ff4318. Report an issue: GitHub.