{"record":{"id":"52fdf8ee54d5e79d","repo":"Billionmail/BillionMail","slug":"error-reading-project-configuration-v","errorCode":null,"errorMessage":"error reading project configuration: %v","messagePattern":"error reading project configuration: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/internal/service/askai/project.go","lineNumber":187,"sourceCode":"\t\tFavicon:       \"\",\n\t\tStatus:        true, // Default status is active\n\t\tKnowledgeBase: []KnowledgeInfo{},\n\t}\n\n\terr := SaveProjectConfig(Domain, config)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error creating project configuration: %v\", err)\n\t}\n\n\treturn nil\n}\n\n// GetBaseInfo retrieves the base information of a project configuration based on the provided domain.\n// It reads the project configuration and returns a ProjectConfig struct containing only the base information.\nfunc GetBaseInfo(Domain string) (ProjectConfig, error) {\n\tconfig, err := ReadProjectConfig(Domain)\n\tif err != nil {\n\t\treturn ProjectConfig{}, fmt.Errorf(\"error reading project configuration: %v\", err)\n\t}\n\n\t// Return only the base information\n\tbaseInfo := ProjectConfig{\n\t\tDomain:        config.Domain,\n\t\tUrls:          config.Urls,\n\t\tProjectName:   config.ProjectName,\n\t\tDescription:   config.Description,\n\t\tIndustry:      config.Industry,\n\t\tPrimaryLogo:   config.PrimaryLogo,\n\t\tSecondaryLogo: config.SecondaryLogo,\n\t\tFavicon:       config.Favicon,\n\t\tUpdateTime:    config.UpdateTime,\n\t\tStatus:        config.Status,\n\t}\n\n\t// Get the knowledge base list\n\t// This will populate the KnowledgeBase field in the baseInfo struct.","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/service/askai/project.go#L169-L205","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Verify the config file exists at PRODUCT_CONFIG_PATH/<domain>/ and is readable by the process user","Check the Domain argument matches the directory name exactly (case, trailing slashes, URL-encoded chars)","Validate the JSON parses (e.g. jq . config.json) and repair or regenerate it","Initialize the project config for this domain before calling GetBaseInfo","Inspect the wrapped inner error text to distinguish file-not-exist vs permission vs JSON-decode causes"],"exampleFix":"// before\nbase, err := askai.GetBaseInfo(domain) // panics/log fails when config missing\n// after\nif !public.FileExists(fmt.Sprintf(PRODUCT_CONFIG_PATH+\"/%s/project.json\", domain)) {\n    if err := askai.InitProjectConfig(domain); err != nil { return err }\n}\nbase, err := askai.GetBaseInfo(domain)","handlingStrategy":"validation","validationCode":"cfgPath := fmt.Sprintf(PRODUCT_CONFIG_PATH+\"/%s/project.json\", domain)\nif !public.FileExists(cfgPath) {\n    return fmt.Errorf(\"project config missing for %s\", domain)\n}\nif _, err := os.Stat(cfgPath); err != nil {\n    return err\n}","typeGuard":"func projectConfigExists(domain string) bool {\n    return public.FileExists(fmt.Sprintf(PRODUCT_CONFIG_PATH+\"/%s/project.json\", domain))\n}","tryCatchPattern":"base, err := askai.GetBaseInfo(domain)\nif err != nil {\n    if strings.Contains(err.Error(), \"error reading project configuration\") {\n        // init or repair config, then retry once\n    }\n    return err\n}","preventionTips":["Always initialize project config before reading it","Validate domain strings (no empty/special chars) before path construction","Run config health checks on startup for all known domains","Mount config volumes read-write with correct ownership","Include the wrapped inner error in logs for fast triage"],"tags":["go","file-io","config"],"backgroundTag":"config-file-read-failed","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}