multica-ai/multica · error

empty identifier

Error message

empty identifier

What it means

quoteQualifiedIdentifier rejects an empty string before building a quoted SQL identifier. Because Postgres cannot take identifiers as query parameters, the function interpolates them via pgx.Identifier.Sanitize, and an empty name would otherwise interpolate to an empty (invalid) reference.

Source

Thrown at server/cmd/migrate/main.go:471

		fmt.Printf("  %s  %s\n", opts.Direction, version)
	}

	return nil
}

// quoteQualifiedIdentifier safely quotes either an unqualified table
// name ("foo") or a schema-qualified name ("schema.foo") for embedding
// into a SQL statement. Postgres does not let parametrized queries
// supply identifiers, so we have to interpolate, but pgx.Identifier
// does the right escaping (double-quotes, embedded-quote handling).
//
// The accepted shape is exactly one or two dot-separated components.
// Names containing more than one dot are rejected outright rather than
// silently sanitized into a "schema"."b.c" reference, which is valid
// SQL but almost certainly not what the caller meant.
func quoteQualifiedIdentifier(name string) (string, error) {
	if name == "" {
		return "", fmt.Errorf("empty identifier")
	}
	parts := strings.Split(name, ".")
	if len(parts) > 2 {
		return "", fmt.Errorf("identifier %q has more than one dot; only schema.table is supported", name)
	}
	for _, p := range parts {
		if p == "" {
			return "", fmt.Errorf("empty component in %q", name)
		}
	}
	return pgx.Identifier(parts).Sanitize(), nil
}

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Trace where the name originates (flag/config) and require it explicitly before calling.
  2. Add a non-empty default or fail fast at flag-parsing time with an actionable message.
  3. Sanitize lists by filtering out empty elements before iterating.

Example fix

// before
q, err := quoteQualifiedIdentifier(tableName)

// after
if strings.TrimSpace(tableName) == "" {
    return fmt.Errorf("--table is required")
}
q, err := quoteQualifiedIdentifier(strings.TrimSpace(tableName))
Defensive patterns

Strategy: validation

Validate before calling

func safeIdentifier(name string) (string, error) {
    name = strings.TrimSpace(name)
    if name == "" {
        return "", fmt.Errorf("table name is required")
    }
    return quoteQualifiedIdentifier(name)
}

Type guard

func isValidIdentifierName(name string) bool {
    if name == "" {
        return false
    }
    for _, p := range strings.Split(name, ".") {
        if p == "" {
            return false
        }
    }
    return len(strings.Split(name, ".")) <= 2
}

Try / catch

q, err := quoteQualifiedIdentifier(name)
if err != nil {
    return fmt.Errorf("invalid table %q from config: %w", name, err)
}

Prevention

When it happens

Trigger: Calling quoteQualifiedIdentifier("") — typically because a table name came from a flag, env var, or config value that was never set or was trimmed to empty.

Common situations: A CLI flag like --table left blank; a config key read with a default of ""; a loop over a list where one element is an empty string after splitting on a delimiter.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/20ce612def523deb. Report an issue: GitHub.