nautechsystems/nautilus_trader · error

{label} contains invalid characters (only alphanumeric and u

Error message

{label} contains invalid characters (only alphanumeric and underscore allowed): {value}

What it means

validate_sql_identifier() enforces that a SQL identifier used by init_postgres/drop_postgres contains only ASCII alphanumerics and underscores. Values containing hyphens, dots, spaces, or other characters are rejected to keep interpolated SQL safe and valid; the message includes the offending value and its label.

Source

Thrown at crates/infrastructure/src/sql/pg.rs:32

// -------------------------------------------------------------------------------------------------

use std::fmt::Debug;

use derive_builder::Builder;
use regex::Regex;
use serde::{Deserialize, Serialize};
use sqlx::{
    AssertSqlSafe, ConnectOptions, PgPool,
    postgres::{PgConnectOptions, PgConnection},
};

fn validate_sql_identifier(value: &str, label: &str) -> anyhow::Result<()> {
    if value.is_empty() {
        anyhow::bail!("{label} must not be empty");
    }

    if !value.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') {
        anyhow::bail!(
            "{label} contains invalid characters (only alphanumeric and underscore allowed): {value}"
        );
    }
    Ok(())
}

fn escape_sql_string(value: &str) -> String {
    value.replace('\'', "''")
}

#[derive(Clone, Serialize, Deserialize, Builder)]
#[serde(deny_unknown_fields)]
#[builder(default)]
#[cfg_attr(
    feature = "python",
    pyo3::pyclass(module = "nautilus_trader.infrastructure", from_py_object)
)]
#[cfg_attr(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Rename the identifier to only letters, digits, and underscores (e.g. my_schema, tenant_42)
  2. Sanitize the value before passing: replace invalid characters with '_' via the same rule the validator uses
  3. If quoting is needed, use a proper Postgres identifier-quoting path instead of raw config values — but note this validator intentionally disallows that input
  4. Read {label} and {value} in the message to find which config field to fix

Example fix

// before
let schema = format!("tenant-{}", tenant_id); // hyphens rejected
// after
let schema = format!("tenant_{}", tenant_id.replace('-', "_"));
assert!(schema.chars().all(|c| c.is_ascii_alphanumeric() || c == '_'));
Defensive patterns

Strategy: validation

Validate before calling

fn sanitize_sql_identifier(v: &str) -> String {
    v.chars().map(|c| if c.is_ascii_alphanumeric() || c == '_' { c } else { '_' }).collect()
}
let schema = sanitize_sql_identifier("tenant-42"); // "tenant_42"

Type guard

fn is_valid_sql_identifier(v: &str) -> bool {
    !v.is_empty() && v.chars().all(|c| c.is_ascii_alphanumeric() || c == '_')
}
assert!(is_valid_sql_identifier(&schema));

Try / catch

if let Err(e) = init_postgres(&opts) {
    if e.to_string().contains("contains invalid characters") {
        return Err(anyhow::anyhow!("Fix Postgres identifier in config: {e}"));
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Calling init_postgres or drop_postgres with an identifier argument (schema, table/catalog name, etc.) that contains characters outside [A-Za-z0-9_], e.g. schema "my-schema" or a table name with a dot.

Common situations: Deriving schema/table names from instance hostnames or container names that contain hyphens; using dots ('mydb.public') where a bare identifier is expected; quotes or spaces pasted into config values; multi-tenant names like 'tenant-42'.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/b72c619b4449ecf0. Report an issue: GitHub.