Billionmail/BillionMail · error

error reading project configuration: %v

Error message

error reading project configuration: %v

What it means

GetBaseInfo reads a domain's project config file via ReadProjectConfig and fails when that underlying read returns any error (missing file, unreadable JSON, path issues). It wraps the cause with 'error reading project configuration: %v' so callers know the failure happened while loading the domain's configuration, before any knowledge-base lookup. The wrapped message includes the original error text.

Source

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

		Favicon:       "",
		Status:        true, // Default status is active
		KnowledgeBase: []KnowledgeInfo{},
	}

	err := SaveProjectConfig(Domain, config)
	if err != nil {
		return fmt.Errorf("error creating project configuration: %v", err)
	}

	return nil
}

// GetBaseInfo retrieves the base information of a project configuration based on the provided domain.
// It reads the project configuration and returns a ProjectConfig struct containing only the base information.
func GetBaseInfo(Domain string) (ProjectConfig, error) {
	config, err := ReadProjectConfig(Domain)
	if err != nil {
		return ProjectConfig{}, fmt.Errorf("error reading project configuration: %v", err)
	}

	// Return only the base information
	baseInfo := ProjectConfig{
		Domain:        config.Domain,
		Urls:          config.Urls,
		ProjectName:   config.ProjectName,
		Description:   config.Description,
		Industry:      config.Industry,
		PrimaryLogo:   config.PrimaryLogo,
		SecondaryLogo: config.SecondaryLogo,
		Favicon:       config.Favicon,
		UpdateTime:    config.UpdateTime,
		Status:        config.Status,
	}

	// Get the knowledge base list
	// This will populate the KnowledgeBase field in the baseInfo struct.

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Verify the config file exists at PRODUCT_CONFIG_PATH/<domain>/ and is readable by the process user
  2. Check the Domain argument matches the directory name exactly (case, trailing slashes, URL-encoded chars)
  3. Validate the JSON parses (e.g. jq . config.json) and repair or regenerate it
  4. Initialize the project config for this domain before calling GetBaseInfo
  5. Inspect the wrapped inner error text to distinguish file-not-exist vs permission vs JSON-decode causes

Example fix

// before
base, err := askai.GetBaseInfo(domain) // panics/log fails when config missing
// after
if !public.FileExists(fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/project.json", domain)) {
    if err := askai.InitProjectConfig(domain); err != nil { return err }
}
base, err := askai.GetBaseInfo(domain)
Defensive patterns

Strategy: validation

Validate before calling

cfgPath := fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/project.json", domain)
if !public.FileExists(cfgPath) {
    return fmt.Errorf("project config missing for %s", domain)
}
if _, err := os.Stat(cfgPath); err != nil {
    return err
}

Type guard

func projectConfigExists(domain string) bool {
    return public.FileExists(fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/project.json", domain))
}

Try / catch

base, err := askai.GetBaseInfo(domain)
if err != nil {
    if strings.Contains(err.Error(), "error reading project configuration") {
        // init or repair config, then retry once
    }
    return err
}

Prevention

When it happens

Trigger: GetBaseInfo(Domain) is called when PRODUCT_CONFIG_PATH/<Domain>/project.json (the config file ReadProjectConfig reads) does not exist, is not readable, or contains invalid JSON.

Common situations: Project never initialized on disk (config file not yet created); domain string misspelled or contains characters that break the path; file permissions deny reading; config JSON corrupted by a partial write or manual edit; deployment volume where configs live not mounted.

Related errors


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