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
- Run askai.Create(Domain, urls) first to generate the project.json for that domain
- Verify the exact Domain string matches the directory name under PRODUCT_CONFIG_PATH (case/spelling)
- Check the PRODUCT_CONFIG_PATH volume is mounted/persistent in deployment
- 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
- Always run Create before any Read/Set operations for a new domain
- Keep domain strings consistent (normalize case, strip slashes) between creation and lookup
- Mount PRODUCT_CONFIG_PATH as a persistent volume in deployments
- Add a setup check that lists existing project directories at startup
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
- error creating project configuration: %v
- error saving default footer config file: %v
- error saving footer config file: %v
- error saving default prompt config file: %v
- error reading prompt config file: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/f2a3073024b885e6.
Report an issue: GitHub.