t8y2/dbx · error

Oracle TNS_ADMIN directory is not accessible: %s

Error message

Oracle TNS_ADMIN directory is not accessible: %s

What it means

oracleTNSNamesPath validates the TNS_ADMIN directory by calling os.Stat on the cleaned path. If Stat fails (missing path, permission denied, bad symlink), the driver cannot locate tnsnames.ora and returns this error with the offending path.

Source

Thrown at agents/drivers/oracle-go/tns.go:90

	if err != nil {
		return "", err
	}
	aliases, err := readOracleTNSAliases(tnsNamesPath, make(map[string]bool), 0)
	if err != nil {
		return "", err
	}
	descriptor, ok := aliases[strings.ToUpper(config.Alias)]
	if !ok {
		return "", fmt.Errorf("Oracle TNS alias %q was not found in %s", config.Alias, tnsNamesPath)
	}
	return descriptor, nil
}

func oracleTNSNamesPath(tnsAdmin string) (string, error) {
	path := filepath.Clean(strings.TrimSpace(tnsAdmin))
	info, err := os.Stat(path)
	if err != nil {
		return "", fmt.Errorf("Oracle TNS_ADMIN directory is not accessible: %s", path)
	}
	if !info.IsDir() {
		return "", fmt.Errorf("Oracle TNS_ADMIN must be a directory containing tnsnames.ora: %s", path)
	}
	tnsNamesPath := filepath.Join(path, "tnsnames.ora")
	if info, err := os.Stat(tnsNamesPath); err != nil || info.IsDir() {
		return "", fmt.Errorf("Oracle tnsnames.ora was not found in TNS_ADMIN directory: %s", path)
	}
	return tnsNamesPath, nil
}

func readOracleTNSAliases(path string, visited map[string]bool, depth int) (map[string]string, error) {
	if depth > 8 {
		return nil, fmt.Errorf("Oracle TNS include depth exceeds 8 files")
	}
	absolutePath, err := filepath.Abs(path)
	if err != nil {
		return nil, fmt.Errorf("Failed to resolve Oracle TNS file path: %w", err)

View on GitHub (pinned to c0390bff16)

Solutions

  1. Verify the path exists: ls -ld <TNS_ADMIN>; fix typos in the configured value.
  2. In containers, mount the directory (docker run -v /host/admin:/opt/oracle/network/admin ...) and use the in-container path.
  3. Fix permissions so the process user can traverse the directory (chmod/chown).
  4. Ensure the value passed in the URL is the server/container filesystem path, not the client machine's path.

Example fix

// before
dsn := "jdbc:oracle:thin:@ALIAS?TNS_ADMIN=/Users/me/Oracle/admin" // path only on laptop
// after (in container)
dsn := "jdbc:oracle:thin:@ALIAS?TNS_ADMIN=/opt/oracle/network/admin"
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(tnsAdmin)
if err != nil || !info.IsDir() {
	return fmt.Errorf("TNS_ADMIN %q must be an existing directory", tnsAdmin)
}

Try / catch

if strings.Contains(err.Error(), "TNS_ADMIN directory is not accessible") {
	return fmt.Errorf("mount or create the TNS_ADMIN directory and fix permissions: %w", err)
}

Prevention

When it happens

Trigger: resolveOracleTNSAlias -> oracleTNSNamesPath receives a TNS_ADMIN value whose path does not exist or is not statable — e.g. a typo'd directory, a path valid on the host but not inside a container, or a permission-blocked directory.

Common situations: TNS_ADMIN set in the JDBC URL/host but the directory only exists on a developer laptop; containerized deployments forgetting to mount the Oracle network admin directory; wrong user permissions (directory owned by another UID); macOS vs Linux path differences.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/70e64205709c3bda. Report an issue: GitHub.