googleapis/mcp-toolbox · error

password is provided without a username. Please provide both

Error message

password is provided without a username. Please provide both a username and password, or leave both fields empty

What it means

getConnectionConfig implements AlloyDB's auth rules: either both username and password (built-in Postgres auth) or neither (IAM auth, where the username is derived from Application Default Credentials). Providing a password with no username is ambiguous/invalid, so it returns this error before any connection attempt.

Source

Thrown at internal/sources/alloydbpg/alloydb_pg.go:188

func getConnectionConfig(ctx context.Context, user, pass, dbname string, readOnly bool) (string, bool, error) {
	userAgent, err := util.UserAgentFromContext(ctx)
	if err != nil {
		userAgent = "genai-toolbox"
	}
	useIAM := true

	var dsn string
	// If username and password both provided, use password authentication
	if user != "" && pass != "" {
		dsn = fmt.Sprintf(passwordDSNFormat, user, pass, dbname, userAgent)
		useIAM = false
	} else if user == "" {
		// If username is empty, fetch email from ADC
		// otherwise, use username as IAM email
		if pass != "" {
			// If password is provided without an username, raise an error
			return "", useIAM, fmt.Errorf("password is provided without a username. Please provide both a username and password, or leave both fields empty")
		}
		email, err := sources.GetIAMPrincipalEmailFromADC(ctx, "postgres")
		if err != nil {
			return "", useIAM, fmt.Errorf("error getting email from ADC: %v", err)
		}
		user = email
		dsn = fmt.Sprintf(iamDSNFormat, user, dbname, userAgent)
	} else {
		// Construct IAM connection string with username
		dsn = fmt.Sprintf(iamDSNFormat, user, dbname, userAgent)
	}

	if readOnly {
		// IMPORTANT: Must use underscore ('alloydb_session_read_only'), NOT a dot.
		// PostgreSQL treats dotted GUCs (e.g. 'alloydb.session_read_only') as custom placeholders
		// and silently ignores them at connection time, leaving the session in read-write mode.
		dsn += " options='-c alloydb_session_read_only=locked'"
	}

View on GitHub (pinned to 8cc6e09de2)

Solutions

  1. Provide both user and password for built-in authentication.
  2. Or remove the password and leave both empty to use IAM auth with ADC.
  3. If using IAM auth, ensure the ADC principal is granted as a database user on the instance.
  4. Validate the source YAML so password is never set without user.

Example fix

// before
sources:
  db:
    kind: alloydb-postgres
    password: secret   # user missing
// after
sources:
  db:
    kind: alloydb-postgres
    user: app-user
    password: secret
Defensive patterns

Strategy: validation

Validate before calling

// Validate auth pair before writing/loading source config
func validAuthConfig(user, password string) error {
    if password != "" && user == "" {
        return fmt.Errorf("password requires a user; provide both or neither (IAM auth)")
    }
    return nil
}

Try / catch

src, err := cfg.Initialize(ctx, tracer)
if err != nil && strings.Contains(err.Error(), "password is provided without a username") {
    return fmt.Errorf("source auth misconfigured: set both user and password, or neither for IAM auth: %w", err)
}

Prevention

When it happens

Trigger: Configuring an alloydb-postgres source with `password` set but `user` empty, without IAM auth intent — detected while resolving connection config during pool initialization.

Common situations: Users setting only a password assuming a default user, or intending IAM auth but supplying a password (IAM auth requires the password field to be empty).

Related errors


AI-assisted analysis of googleapis/mcp-toolbox@8cc6e09de2 (2026-09-05). Data as JSON: /api/errors/130aede686b92c81. Report an issue: GitHub.