OpenNHP/opennhp · error

fail to get base directory absolute path

Error message

fail to get base directory absolute path: %w

What it means

loadResource resolves the KBS resource base directory to an absolute path via filepath.Abs. This error is returned when filepath.Abs(baseDir) fails (wrapped as 'fail to get base directory absolute path: %w'). filepath.Abs only fails when os.Getwd fails, meaning the process working directory was deleted or is inaccessible.

Solutions

  1. Restore a valid working directory or restart the daemon from an existing directory
  2. Set a stable WorkingDirectory in the service unit / WORKDIR in the container
  3. Make baseDir an absolute value configured at startup so filepath.Abs is a no-op path
  4. Cache the resolved base directory at init instead of per-request
  5. Check the wrapped error to confirm getwd failure before deeper debugging

Example fix

// before
absBaseDir, err := filepath.Abs(baseDir)
if err != nil {
	return nil, fmt.Errorf("fail to get base directory absolute path: %w", err)
}
// after (resolve once at init from an explicit absolute base)
if !filepath.IsAbs(baseDir) {
	return nil, fmt.Errorf("baseDir must be absolute, got %q", baseDir)
}
absBaseDir := baseDir
Defensive patterns

Strategy: validation

Validate before calling

if !filepath.IsAbs(baseDir) {
	return fmt.Errorf("baseDir must be configured as an absolute path, got %q", baseDir)
}
if fi, err := os.Stat(baseDir); err != nil || !fi.IsDir() {
	return fmt.Errorf("baseDir %q does not exist", baseDir)
}

Try / catch

data, err := loadResource(resourceID)
if err != nil {
	if strings.Contains(err.Error(), "fail to get base directory absolute path") {
		http.Error(w, "resource store unavailable", http.StatusInternalServerError)
		return
	}
	http.Error(w, "resource not found", http.StatusNotFound)
	return
}

Prevention

When it happens

Trigger: GetResource calls loadResource while the process's current working directory no longer exists (deleted/moved after start), making os.Getwd fail inside filepath.Abs.

Common situations: Daemon started in a temp directory that was later removed; running under a container with a stale workdir; systemd/chroot environments where the cwd is unmounted.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of OpenNHP/opennhp@6e04ca5ff0 (2026-09-07). Data as JSON: /api/errors/38282c448cca1b67. Report an issue: GitHub.

Appendix: source

Thrown at endpoints/server/kbs/resource/resource.go:161

		"enc": "A256GCM",
	}
	protectedJSON, _ := json.Marshal(protected)

	response := map[string]string{
		"protected":     string(protectedJSON),
		"encrypted_key": base64.RawURLEncoding.EncodeToString(encryptedKey),
		"iv":            base64.RawURLEncoding.EncodeToString(iv),
		"ciphertext":    base64.RawURLEncoding.EncodeToString(encryptedContent),
		"tag":           "",
	}

	c.JSON(http.StatusOK, response)
}

func loadResource(resourceID string) ([]byte, error) {
	absBaseDir, err := filepath.Abs(baseDir)
	if err != nil {
		return nil, fmt.Errorf("fail to get base directory absolute path: %w", err)
	}

	fullPath := filepath.Join(absBaseDir, resourceID)

	absFullPath, err := filepath.Abs(fullPath)
	if err != nil {
		return nil, fmt.Errorf("fail to get resource absolute path: %w", err)
	}

	// Check if the path is within the base directory to avoid path traversal attack.
	if !strings.HasPrefix(absFullPath, absBaseDir) {
		return nil, errors.New("invalid resource ID: potential path traversal attack")
	}

	if _, statErr := os.Stat(absFullPath); statErr != nil {
		if os.IsNotExist(statErr) {
			return nil, errors.New("resource not found")
		}

View on GitHub (pinned to 6e04ca5ff0)