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

  1. Read the wrapped %v error to identify the OS-level cause (ENOENT, EACCES, ENOSPC, EISDIR)
  2. 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
  3. Ensure the process user owns/has write access to PRODUCT_CONFIG_PATH (chown/chmod or fix the volume mount)
  4. Verify Kid and Domain contain no path separators or invalid filesystem characters
  5. 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

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


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/dab497508d763d45. Report an issue: GitHub.