t8y2/dbx · error

Oracle TNS_ADMIN directory is required

Error message

Oracle TNS_ADMIN directory is required

What it means

parseOracleTNSJDBCURL requires a query string in the JDBC-style URL. If the target contains no '?' (len(parts) == 1), there is nowhere to carry TNS_ADMIN, so the driver rejects the URL demanding a TNS_ADMIN directory specification.

Source

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

func parseOracleTNSJDBCURL(value string) (oracleTNSConfig, bool, error) {
	source := strings.TrimSpace(value)
	if !strings.HasPrefix(strings.ToLower(source), oracleJDBCThinPrefix) {
		return oracleTNSConfig{}, false, nil
	}

	target := strings.TrimSpace(source[len(oracleJDBCThinPrefix):])
	if target == "" || strings.HasPrefix(target, "(") || strings.HasPrefix(target, "//") || strings.Contains(strings.SplitN(target, "?", 2)[0], ":") {
		return oracleTNSConfig{}, false, nil
	}

	parts := strings.SplitN(target, "?", 2)
	alias, err := url.QueryUnescape(strings.TrimSpace(parts[0]))
	if err != nil || strings.TrimSpace(alias) == "" {
		return oracleTNSConfig{}, true, fmt.Errorf("Oracle TNS network alias is invalid")
	}
	if len(parts) == 1 {
		return oracleTNSConfig{}, true, fmt.Errorf("Oracle TNS_ADMIN directory is required")
	}
	query, err := url.ParseQuery(parts[1])
	if err != nil {
		return oracleTNSConfig{}, true, fmt.Errorf("Oracle TNS connection parameters are invalid: %w", err)
	}
	tnsAdmin := strings.TrimSpace(query.Get("TNS_ADMIN"))
	if tnsAdmin == "" {
		return oracleTNSConfig{}, true, fmt.Errorf("Oracle TNS_ADMIN directory is required")
	}
	return oracleTNSConfig{Alias: strings.TrimSpace(alias), TNSAdmin: tnsAdmin}, true, nil
}

func resolveOracleTNSAlias(config oracleTNSConfig) (string, error) {
	tnsNamesPath, err := oracleTNSNamesPath(config.TNSAdmin)
	if err != nil {
		return "", err
	}
	aliases, err := readOracleTNSAliases(tnsNamesPath, make(map[string]bool), 0)

View on GitHub (pinned to c0390bff16)

Solutions

  1. Append the query component: jdbc:oracle:thin:@ALIAS?TNS_ADMIN=/path/to/tnsadmin.
  2. Alternatively set the TNS_ADMIN environment variable and verify the driver picks it up, per the library's documented config precedence.
  3. If you meant a plain host DSN, use the non-TNS URL form instead of an alias.
  4. Check that the URL wasn't truncated when copied from documentation or a secret manager.

Example fix

// before
dsn := "jdbc:oracle:thin:@PROD_DB" // no TNS_ADMIN
// after
dsn := "jdbc:oracle:thin:@PROD_DB?TNS_ADMIN=/opt/oracle/network/admin"
Defensive patterns

Strategy: validation

Validate before calling

if !strings.Contains(target, "?") || !strings.Contains(target, "TNS_ADMIN=") {
	return errors.New("TNS JDBC URL must include ?TNS_ADMIN=<dir>")
}

Try / catch

if err != nil && strings.Contains(err.Error(), "TNS_ADMIN directory is required") {
	return fmt.Errorf("append ?TNS_ADMIN=/path/to/admin to the Oracle JDBC URL: %w", err)
}

Prevention

When it happens

Trigger: buildDSNForConnect is given jdbc:oracle:thin:@ALIAS with no '?TNS_ADMIN=...' query component, so the parser cannot locate the tnsnames.ora directory.

Common situations: Migrating from a plain host:port DSN to TNS alias form and forgetting the TNS_ADMIN query parameter; environment variables set but URL not updated; trimming the URL at '?' by mistake.

Understand the failure class

Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.

Related errors


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