nautechsystems/nautilus_trader · error

{label} must not be empty

Error message

{label} must not be empty

What it means

validate_sql_identifier() in crates/infrastructure/src/sql/pg.rs rejects an empty string before doing any character validation. init_postgres/drop_postgres call it for SQL identifiers (schema, database/table names, etc.) because empty identifiers would produce invalid or dangerous SQL. The error interpolates the caller-supplied label naming which identifier was empty.

Source

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

//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// -------------------------------------------------------------------------------------------------

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(

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set the missing identifier explicitly in the Postgres connection/config (e.g. schema: "public")
  2. Check the env var or config field feeding the identifier — it is resolving to an empty string; give it a default
  3. Validate the config at startup with the same rules (non-empty, alphanumeric+underscore) before calling init_postgres
  4. Read the {label} in the message to identify exactly which identifier is empty

Example fix

// before
let opts = ConnectOptions::from_uri(&uri)?; // schema left empty
// after
let schema = std::env::var("NAUTILUS_PG_SCHEMA").unwrap_or_else(|_| "public".to_string());
opts.schema(&schema); // non-empty, validated identifier
Defensive patterns

Strategy: validation

Validate before calling

fn ensure_non_empty(value: &str, label: &str) -> Result<(), String> {
    if value.is_empty() { Err(format!("{label} must not be empty")) } else { Ok(()) }
}
ensure_non_empty(&config.schema, "schema")?;

Type guard

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

Try / catch

if let Err(e) = init_postgres(&opts) {
    if e.to_string().contains("must not be empty") {
        return Err(anyhow::anyhow!("Postgres config incomplete: {e}"));
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Calling init_postgres or drop_postgres with an empty value for any identifier argument it validates (e.g. empty schema name), typically via connection/config options where a field was left unset.

Common situations: Postgres config where schema/database name is an empty string or an unset env var yields ""; programmatic construction of ConnectOptions where a default field was never filled; YAML/TOML config with an empty value like schema: "".

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


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