Billionmail/BillionMail · error
error reading knowledge base file: %v
Error message
error reading knowledge base file: %v
What it means
After confirming the knowledge file exists, ReadKnowledgeBase reads it with os.ReadFile. If the OS read fails (permission denied, I/O error, file removed between the existence check and read), the error is wrapped as 'error reading knowledge base file: %v'. This is distinct from the not-exist error and signals an actual read operation failure.
Source
Thrown at core/internal/service/askai/project.go:296
}
err = SaveProjectConfig(Domain, config)
if err != nil {
return fmt.Errorf("error saving project configuration: %v", err)
}
return nil
}
// ReadKnowledgeBase reads a specific knowledge base from a JSON file based on the provided domain and knowledge ID.
// It returns a KnowledgeInfo struct or an error if the file does not exist or cannot be
func ReadKnowledgeBase(Domain string, Kid string) (KnowledgeInfo, error) {
filename := fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/knowledge/%s.json", Domain, Kid)
if !public.FileExists(filename) {
return KnowledgeInfo{}, fmt.Errorf("knowledge base file does not exist: %s", filename)
}
data, err := os.ReadFile(filename)
if err != nil {
return KnowledgeInfo{}, fmt.Errorf("error reading knowledge base file: %v", err)
}
var knowledge KnowledgeInfo
err = json.Unmarshal(data, &knowledge)
if err != nil {
return KnowledgeInfo{}, fmt.Errorf("error unmarshalling knowledge base: %v", err)
}
return knowledge, nil
}
// 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)View on GitHub (pinned to fc36c76c05)
Solutions
- Check permissions on the knowledge JSON file for the process user
- Re-run the request; a TOCTOU race (file deleted between check and read) is transient
- Verify the path is a regular file, not a directory (os.Stat / mode check)
- Inspect the wrapped inner error (syscall text) for the exact cause
- Restore or re-save the knowledge file if it was removed
Example fix
// before
kb, err := askai.ReadKnowledgeBase(domain, kid)
// after
kb, err := askai.ReadKnowledgeBase(domain, kid)
if err != nil && strings.Contains(err.Error(), "reading knowledge base file") {
time.Sleep(100 * time.Millisecond) // transient race?
kb, err = askai.ReadKnowledgeBase(domain, kid)
} Defensive patterns
Strategy: retry
Validate before calling
kbPath := fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/knowledge/%s.json", domain, kid)
fi, err := os.Stat(kbPath)
if err != nil || fi.IsDir() {
return fmt.Errorf("knowledge %s not a readable file", kid)
}
if f, err := os.Open(kbPath); err != nil {
return err
} else {
f.Close()
} Type guard
func knowledgeReadable(domain, kid string) bool {
f, err := os.Open(fmt.Sprintf(PRODUCT_CONFIG_PATH+"/%s/knowledge/%s.json", domain, kid))
if err != nil { return false }
f.Close()
return true
} Try / catch
var kb askai.KnowledgeInfo
var err error
for i := 0; i < 3; i++ {
kb, err = askai.ReadKnowledgeBase(domain, kid)
if err == nil || !strings.Contains(err.Error(), "reading knowledge base file") {
break
}
time.Sleep(100 * time.Millisecond << i)
} Prevention
- Use atomic writes (temp + rename) so readers never see partial files
- Keep knowledge files owned/readable by the service user
- Add small retry with backoff for transient I/O errors
- Verify paths resolve to regular files, not directories
- Log syscall-level inner errors for storage diagnostics
When it happens
Trigger: ReadKnowledgeBase(Domain, Kid) where FileExists passed but os.ReadFile fails: permission change, file deleted in TOCTOU window, I/O error, or path is a directory not a file.
Common situations: Race with a concurrent delete/save; root-owned file read by an unprivileged process; Kid resolving to a directory named '<kid>.json'; NFS/storage transient failures.
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 getting knowledge base list: %v
- knowledge base file does not exist: %s
- error reading project configuration: %v
- error saving project configuration: %v
- error unmarshalling knowledge base: %v
AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05).
Data as JSON: /api/errors/6fa888e61912ecae.
Report an issue: GitHub.