Billionmail/BillionMail · error
error writing knowledge base file: %v
Error message
error writing knowledge base file: %v
What it means
After successfully marshalling the KnowledgeInfo struct, SaveKnowledgeBase writes the JSON bytes to <configPath>/<domain>/knowledge/<kid>.json with os.WriteFile. This error wraps any failure of that write: missing parent directory, permission denied, disk full, or the target path being a directory. The directory creation via os.MkdirAll on line 312 ignores its own error, so a failed mkdir surfaces here instead.
Source
Thrown at core/internal/service/askai/project.go:323
}
// SaveKnowledgeBase saves the provided KnowledgeInfo to a JSON file based on the domain and knowledge ID.
// It creates the directory if it does not exist and writes the knowledge information to a JSON file
func SaveKnowledgeBase(Domain string, knowledge KnowledgeInfo) error {
knowledgePath := fmt.Sprintf("%s/%s/knowledge", PRODUCT_CONFIG_PATH, Domain)
if !public.FileExists(knowledgePath) {
os.MkdirAll(knowledgePath, os.ModePerm)
}
filename := fmt.Sprintf("%s/%s.json", knowledgePath, knowledge.Kid)
configStr, err := json.MarshalIndent(knowledge, "", " ")
if err != nil {
return fmt.Errorf("error marshalling knowledge base: %v", err)
}
err = os.WriteFile(filename, configStr, os.ModePerm)
if err != nil {
return fmt.Errorf("error writing knowledge base file: %v", err)
}
return nil
}
// GetKnowledgeBaseList retrieves a list of all knowledge bases for a given domain.
// It reads the knowledge base directory, iterates through the files, and returns a slice of KnowledgeInfo structs.
// If the directory does not exist or cannot be read, it returns an error.
func GetKnowledgeBaseList(Domain string) ([]KnowledgeInfo, error) {
knowledgePath := fmt.Sprintf("%s/%s/knowledge", PRODUCT_CONFIG_PATH, Domain)
if !public.FileExists(knowledgePath) {
os.MkdirAll(knowledgePath, os.ModePerm)
// If the knowledge base directory does not exist, create it
}
files, err := os.ReadDir(knowledgePath)
if err != nil {
return nil, fmt.Errorf("error reading knowledge base directory: %v", err)
}View on GitHub (pinned to fc36c76c05)
Solutions
- Read the wrapped %v error to identify the OS-level cause (ENOENT, EACCES, ENOSPC, EISDIR)
- Verify the parent directory exists and is writable: check PRODUCT_CONFIG_PATH/<domain>/knowledge permissions; fix MkdirAll to check its error instead of ignoring it
- Ensure the process user owns/has write access to PRODUCT_CONFIG_PATH (chown/chmod or fix the volume mount)
- Verify Kid and Domain contain no path separators or invalid filesystem characters
- Check disk space/quotas with df
Example fix
// before
if !public.FileExists(knowledgePath) {
os.MkdirAll(knowledgePath, os.ModePerm) // error ignored
}
// after
if err := os.MkdirAll(knowledgePath, 0o755); err != nil {
return fmt.Errorf("error creating knowledge dir: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
func canWriteKnowledgeDir(domain string) error {
dir := fmt.Sprintf("%s/%s/knowledge", PRODUCT_CONFIG_PATH, domain)
if err := os.MkdirAll(dir, 0o755); err != nil {
return err
}
f, err := os.CreateTemp(dir, ".wtest*")
if err != nil {
return err
}
f.Close()
return os.Remove(f.Name())
} Try / catch
if err := SaveKnowledgeBase(domain, kb); err != nil {
var pe *fs.PathError
if errors.As(err, &pe) || strings.Contains(err.Error(), "writing") {
log.Errorf("KB write failed for %s: %v — check permissions/disk", kb.Kid, err)
}
} Prevention
- Verify PRODUCT_CONFIG_PATH is on a writable volume at startup
- Run a write-probe health check on boot
- Run the service under a user that owns the config directory
- Monitor disk space; alert before ENOSPC
- Validate Domain/Kid contain no path separators
When it happens
Trigger: os.WriteFile fails because: the knowledge directory does not exist and MkdirAll silently failed (ignored error on line 312); the process lacks write permission on PRODUCT_CONFIG_PATH; the disk is full; <kid>.json exists as a directory; the path contains invalid characters from Domain/Kid.
Common situations: Read-only container volume or read-only filesystem mount; PRODUCT_CONFIG_PATH misconfigured to a non-writable location; running the service as a non-root user after files were created by root; domain or Kid containing path separators/invalid chars creating a broken path; disk quota exhausted.
Understand the failure class
Background: "failed to write file", "Could not save figure", "Error saving remote file" — file write failed: causes and fixes across languages and libraries — this error's family across 38 libraries.
Related errors
- error reading project configuration file: %v
- error writing project configuration file: %v
- error creating company profile file: %v
- error reading 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/dab497508d763d45.
Report an issue: GitHub.