Billionmail/BillionMail · error

project configuration file does not exist: %s

Error message

project configuration file does not exist: %s

What it means

ReadProjectConfig builds the path PRODUCT_CONFIG_PATH/<Domain>/project.json and requires it to exist before reading. If public.FileExists reports false, it returns this error naming the missing file, signaling the project was never initialized for that domain.

Source

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

type ImageInfo struct {
	ImageId    string `json:"image_id"`    // 图片ID
	ImageUrl   string `json:"image_url"`   // 图片URL
	Filename   string `json:"filename"`    // 图片文件名
	AltText    string `json:"alt_text"`    // 图片替代文本
	ImageTag   string `json:"image_tag"`   // 图片标签
	UpdateTime int64  `json:"update_time"` // 更新时间
	Size       string `json:"size"`        // 图片大小 80x80
}

// ReadProjectConfig reads the project configuration from a JSON file based on the provided domain.
// It returns a ProjectConfig struct or an error if the file does not exist or cannot be read.
func ReadProjectConfig(Domain string) (ProjectConfig, error) {

	filename := fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/project.json", Domain)
	// Here you would implement the logic to read the project configuration from the file.
	// For now, we will just return a placeholder string.
	if !public.FileExists(filename) {
		return ProjectConfig{}, fmt.Errorf("project configuration file does not exist: %s", filename)
	}
	data, err := os.ReadFile(filename)
	if err != nil {
		return ProjectConfig{}, fmt.Errorf("error reading project configuration file: %v", err)
	}

	var config ProjectConfig
	err = json.Unmarshal(data, &config)
	if err != nil {
		return ProjectConfig{}, fmt.Errorf("error unmarshalling project configuration: %v", err)
	}
	return config, nil
}

// SaveProjectConfig saves the provided ProjectConfig to a JSON file based on the domain.
// It creates the directory if it does not exist and writes the configuration to project.json.
// If the file cannot be written, it returns an error.
// If the directory does not exist, it creates it with appropriate permissions.

View on GitHub (pinned to fc36c76c05)

Solutions

  1. Run askai.Create(Domain, urls) first to generate the project.json for that domain
  2. Verify the exact Domain string matches the directory name under PRODUCT_CONFIG_PATH (case/spelling)
  3. Check the PRODUCT_CONFIG_PATH volume is mounted/persistent in deployment
  4. Handle the error by prompting the user to set up the project instead of failing the whole request

Example fix

// before
cfg, err := askai.ReadProjectConfig(domain)
if err != nil { return err }
// after
cfg, err := askai.ReadProjectConfig(domain)
if err != nil && strings.Contains(err.Error(), "does not exist") {
    if err := askai.Create(domain, []string{"https://" + domain}); err != nil { return err }
    cfg, err = askai.ReadProjectConfig(domain)
}
if err != nil { return err }
Defensive patterns

Strategy: validation

Validate before calling

filename := filepath.Join(productConfigPath, domain, "project.json")
if _, err := os.Stat(filename); os.IsNotExist(err) {
    // initialize first
    if err := askai.Create(domain, []string{"https://" + domain}); err != nil { return err }
}

Try / catch

cfg, err := askai.ReadProjectConfig(domain)
if err != nil {
    if strings.Contains(err.Error(), "does not exist") {
        return handleUninitializedProject(domain) // create or inform user
    }
    return err
}

Prevention

When it happens

Trigger: Any of GetProjectConfigPrompt, GetBaseInfo, GetProjectStatus, SetProjectStatus, ModifyBaseInfo, AutoGetProjectInfo calls ReadProjectConfig for a domain whose project.json was never created (Create not run), was deleted, or whose Domain string mismatches the on-disk directory (case, trailing slash, wrong domain).

Common situations: Fresh deployment where projects were never created; data volume not mounted so PRODUCT_CONFIG_PATH is empty; domain renamed/case-mismatch between DB and filesystem; manually cleaning the storage directory.

Understand the failure class

Background: "Config file not found": what it means and how to fix it in docker-sync, Maven, Vagrant, Turborepo and other tools — this error's family across 60 libraries.

Related errors


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