Billionmail/BillionMail · error
error reading company profile file: %v
Error message
error reading company profile file: %v
What it means
When company_profile.json exists, ReadCompanyProfile loads it with os.ReadFile. This error wraps a read failure on an existing file — the file passed the FileExists check but could not actually be read, usually due to permissions, the path being a directory, or a TOCTOU deletion between the check and the read.
Source
Thrown at core/internal/service/askai/project.go:448
// If the company profile file does not exist, return a default profile
// This allows the system to handle cases where the profile has not been set up yet
// and avoids errors when trying to read a non-existent file.
// It also allows the user to create a new profile without needing to handle file not
// found errors.
companyProfileDefault.UpdateTime = public.GetNowTime()
companyProfileJson, err := json.MarshalIndent(companyProfileDefault, "", " ")
if err != nil {
return CompanyProfile{}, fmt.Errorf("error marshalling company profile: %v", err)
}
err = os.WriteFile(filename, companyProfileJson, 0644)
if err != nil {
return CompanyProfile{}, fmt.Errorf("error creating company profile file: %v", err)
}
return companyProfileDefault, nil
}
data, err := os.ReadFile(filename)
if err != nil {
return CompanyProfile{}, fmt.Errorf("error reading company profile file: %v", err)
}
var profile CompanyProfile
err = json.Unmarshal(data, &profile)
if err != nil {
return CompanyProfile{}, fmt.Errorf("error unmarshalling company profile: %v", err)
}
return profile, nil
}
// SaveCompanyProfile saves the provided CompanyProfile to a JSON file based on the domain.
// It creates the directory if it does not exist and writes the profile information to company_profile.json
func SaveCompanyProfile(Domain string, profile CompanyProfile) error {
filename := fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/company_profile.json", Domain)
data, err := json.Marshal(profile)
if err != nil {
return fmt.Errorf("error marshalling company profile: %v", err)
}
err = os.WriteFile(filename, data, 0644)View on GitHub (pinned to fc36c76c05)
Solutions
- Read the wrapped %v error for the OS cause (EACCES, EISDIR, ENOENT)
- Fix file permissions/ownership so the service user can read company_profile.json
- If a directory occupies the name, remove it and let the lazy-create path regenerate the default
- Handle the race by attempting ReadFile first and treating os.IsNotExist as 'create default' instead of pre-checking FileExists
Example fix
// before
if !public.FileExists(filename) { /* create default */ }
data, err := os.ReadFile(filename)
// after
data, err := os.ReadFile(filename)
if os.IsNotExist(err) { /* create default */ } else if err != nil {
return CompanyProfile{}, fmt.Errorf("error reading company profile file: %w", err)
} Defensive patterns
Strategy: try-catch
Validate before calling
p := fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/company_profile.json", domain)
if fi, err := os.Stat(p); err == nil {
if fi.IsDir() {
return fmt.Errorf("%s is a directory", p)
}
f, err := os.OpenFile(p, os.O_RDONLY, 0)
if err != nil {
return fmt.Errorf("profile unreadable: %w", err)
}
f.Close()
} Try / catch
profile, err := ReadCompanyProfile(domain)
if err != nil && strings.Contains(err.Error(), "reading company profile file") {
if os.IsPermission(errors.Unwrap(err)) {
log.Errorf("Permission denied on %s profile", domain)
}
// fall back to an empty default profile
profile = CompanyProfile{}
} Prevention
- Read-first (treat os.IsNotExist as create-default) instead of FileExists pre-checks
- Keep profile files owned/readable by the service user
- Never create directories named company_profile.json
- Validate file readability in startup health checks
When it happens
Trigger: os.ReadFile(filename) fails though FileExists returned true: permission denied on the file; company_profile.json is a directory; file deleted concurrently between FileExists and ReadFile; I/O error on the underlying storage.
Common situations: Profile file created by root, service running as unprivileged user; a directory accidentally named company_profile.json; concurrent initialization racing to create/read the profile; corrupted volume.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- error reading project configuration file: %v
- error writing project configuration file: %v
- error writing knowledge base file: %v
- error creating company profile file: %v
- error saving prompt config file: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/14ce2b2c533af98e.
Report an issue: GitHub.