Version: dev

validate

Stable function · Validation

Tier: stable · Kind: function · Topic: Validation

JuliaTypeScriptPythonRustGo
validatevalidatevalidatevalidateValidate

Julia

validate(file::EsmFile)
validate(file::EsmFile) -> ValidationResult

Complete validation combining schema, structural, and unit validation. Returns ValidationResult with all errors and warnings.

Source

Example (validate)

result = validate(doc)
@assert result isa ValidationResult
@assert result.is_valid

# A document that loads fine but uses a variable it never declares. Validation
# reports the problem in the result rather than throwing.
bad = validate_path(joinpath(FIXTURES, "invalid.esm"))
@assert !bad.is_valid
err = only(bad.structural_errors)
println(err.path, ": ", err.message)
@assert err.message == "Variable 'k' referenced in equation is not declared"
@assert err.path == "/models/Broken/equations/0/rhs"

From docs/api/examples/julia/documents.jl

TypeScript

function validate(document: EsmFile | object, options?: ValidateOptions): ValidationResult

Validate a TYPED ESM DOCUMENT and return a structured validation result.

API_SPEC.md §8 item 13: validate takes a typed document in EVERY binding. To validate JSON text, call validateText .

Passing a string is rejected at compile time by the signature and at runtime by an explicit guard, rather than silently doing something else.

Parameters

  • document — a loaded ESM document (or a plain object of the same shape)
  • options — Optional ValidateOptions; pass basePath to let relative {ref} / template-import targets be opened and resolved.

Returns

ValidationResult with validation status and errors

Source

Example (validate)

// A good document validates cleanly.
const good = validate(loadPath(fixture('decay.esm')))
assert.equal(good.is_valid, true)
assert.deepEqual(good.structural_errors, [])

// `validate` reports problems in its result; it does not throw. invalid.esm
// uses a variable `k` that its model never declares.
const bad = validateText(readFileSync(fixture('invalid.esm'), 'utf8'))
assert.equal(bad.is_valid, false)
assert.equal(bad.schema_errors.length, 0)
const [err] = bad.structural_errors
assert.equal(err.code, 'undefined_variable')
assert.equal(err.path, '/models/Broken/equations/0/rhs')
assert.match(err.message, /Variable "k" referenced in equation is not declared/)

// Loading a structurally invalid document still succeeds. Unit warnings found
// while loading go to `console.warn` unless you collect them yourself.
const warnings: UnitWarning[] = []
const broken = loadPath(fixture('invalid.esm'), { onUnitWarning: (w) => warnings.push(w) })
assert.equal(validate(broken).is_valid, false)
assert.match(warnings[0].message, /Unknown variable: k/)

// Text that is not JSON at all is a `ParseError`, thrown at load time.
assert.throws(() => loadString('{ not json'), ParseError)

From docs/api/examples/typescript/validate.ts

Python

validate(esm_file: EsmFile, *, base_path: str | None = None) -> ValidationResult

Validate a parsed ESM document against structural and unit requirements.

esm_file is a typed EsmFile — the one input type validate accepts in every binding (API_SPEC.md §8 item 13). It does not accept a path, JSON text or a raw dict; use the explicit entry points instead:

This function implements comprehensive validation including:

  1. Equation-unknown balance
  2. Reference integrity (variable refs, scoped refs, event affects, coupling refs, operator refs)
  3. Reaction consistency (species declared, positive stoichiometries, no null-null, rate refs)
  4. Event consistency (condition types, affect vars, functional affect refs)

Parameters

  • esm_file (EsmFile) — The parsed EsmFile to validate.

  • base_path (str | None) — Directory that relative {"ref": ...} subsystem/model mounts (§4.7) and expression_template_imports (§9.7.2) resolve against.

    A document that came through load_path resolved its mounts already, so this mainly matters on the validate_text / validate_path paths, which forward it to the loader: text carries no location of its own, and without an anchor every subsystem-ref and template-import fixture becomes unsatisfiable. A MISSING target then yields unresolved_subsystem_ref (or the template-import equivalent) at the mount’s pointer, and a PRESENT one validates through.

Returns

  • ValidationResult — ValidationResult containing schema_errors, structural_errors, unit_warnings, and is_valid flag

Raises

  • TypeError — if esm_file is not an EsmFile .

Source

Example (validate)

result = earthsci_ast.validate(doc)
assert result.is_valid
assert result.schema_errors == [] and result.structural_errors == []

# validate_path reports problems in the result; it does not raise.
bad = earthsci_ast.validate_path(FIXTURES / "invalid.esm")
assert not bad.is_valid
error = bad.structural_errors[0]
print(error.code, error.path, error.message)
assert error.code == "undefined_variable"
assert "'k'" in error.message

# Loading the same file raises, because loading validates too.
try:
    earthsci_ast.load_path(FIXTURES / "invalid.esm")
except earthsci_ast.SchemaValidationError as exc:
    assert "'k'" in str(exc)
else:
    raise AssertionError("loading invalid.esm should fail")

From docs/api/examples/python/documents.py

Rust

pub fn validate(esm_file: &EsmFile) -> ValidationResult

Perform structural validation on an ESM file

Note: This function performs ONLY structural validation, not schema validation. For comprehensive validation (both schema and structural), use validate_text() instead.

This function runs the structural checks (delegating to crate::structural and crate::coupling):

  • All variable references are defined (including scoped refs resolved via the subsystem hierarchy)
  • Equation-unknown balance (ODE count vs. state variables)
  • Observed variables carry expressions
  • Discrete/continuous event references
  • Reaction species/stoichiometry consistency
  • Coupling-entry well-formedness
  • Dimensional consistency of equations — reported as unit_warnings, never as errors

Arguments

  • esm_file - The ESM file to validate (already parsed and schema-validated)

Returns

  • ValidationResult - Structural validation results (schema_errors will always be empty)

Examples

use earthsci_ast::{validate, load_string, EsmFile, Metadata};

let json_str = r#"
{
  "esm": "1.0.0",
  "metadata": {"name": "test"},
  "models": {"simple": {"variables": {}, "equations": []}}
}
"#;

// First load and parse (includes schema validation)
let esm_file = load_string(json_str).unwrap();

// Then do structural validation
let result = validate(&esm_file);
assert!(result.is_valid);
assert!(result.schema_errors.is_empty()); // Always empty for this function

Source · Rust docs

Example (validate)

let good = load_path(fixture("decay.esm"))?;
let result = validate(&good);
assert!(result.is_valid);
assert!(result.schema_errors.is_empty() && result.structural_errors.is_empty());

// invalid.esm is well-formed JSON that matches the schema, so it loads;
// validation then reports the undeclared variable `k` as a structural
// error. Validation returns a result object, it does not fail.
let bad = load_path(fixture("invalid.esm"))?;
let result = validate(&bad);
assert!(!result.is_valid);
for err in &result.structural_errors {
    println!("{}: [{:?}] {}", err.path, err.code, err.message);
}
assert!(result.structural_errors.iter().any(|e| e.message.contains("'k'")));

// `validate_text` starts from the JSON text, so a document that does not
// even load is reported in the same result shape instead of as an error.
let text = std::fs::read_to_string(fixture("invalid.esm"))?;
let from_text = validate_text(&text, None);
assert!(!from_text.is_valid);
let not_json = validate_text("{ \"esm\": ", None);
assert!(!not_json.is_valid);

From docs/api/examples/rust/validate.rs

Go

func Validate(file *ESMFile) *ValidationResult

Validate performs semantic validation of an already-parsed ESM document and returns the four-field ValidationResult of esm-libraries-spec §3.4.

Canonical validate (API_SPEC.md §8 items 12 and 13): the input is a TYPED DOCUMENT in every binding, and the return is the four-field shape in every binding. ValidateStructural still offers the message-oriented DetailedValidationResult form.

SchemaErrors is always EMPTY, exactly as Rust’s validate documents: a *ESMFile can only exist by having come through LoadString/LoadPath/ LoadDocument, all of which schema-validate and refuse to return a document that fails. Validating text that has NOT been through the schema is ValidateText’s job.

IsValid counts hard structural errors only. Warning-level findings (StructuralError.Level == “warning”, e.g. duplicate_reaction_species) are advisory and do not invalidate the document.

Source · Go docs

Example (edit)

doc, err := esm.LoadPath(fixture("decay.esm"))
if err != nil {
	log.Fatal(err)
}

units, desc := "mol", "Amount decayed so far"
model := esm.AddVariable(doc.Models["Decay"], "decayed", esm.ModelVariable{
	Type: "unknown", Units: &units, Description: &desc,
})
eq, err := esm.ParseEquation("decayed = 100 - N")
if err != nil {
	log.Fatal(err)
}
model = esm.AddEquation(model, *eq)
doc.Models["Decay"] = model
fmt.Println(len(model.Equations), esm.Validate(doc).IsValid)

text, err := esm.ToJSON(doc)
if err != nil {
	log.Fatal(err)
}
fmt.Println(strings.Contains(text, `"decayed"`))

path := filepath.Join(dir, "decay-edited.esm")
if err := esm.WritePath(doc, path); err != nil {
	log.Fatal(err)
}
reread, err := esm.LoadPath(path)
if err != nil {
	log.Fatal(err)
}
fmt.Println(sortedKeys(reread.Models["Decay"].Variables))

From docs/api/examples/go/edit_test.go

Example (validate)

doc, err := esm.LoadPath(fixture("decay.esm"))
if err != nil {
	log.Fatal(err)
}
fmt.Println(esm.Validate(doc).IsValid)

// invalid.esm is schema-clean but its equation reads an undeclared `k`.
text, err := os.ReadFile(fixture("invalid.esm"))
if err != nil {
	log.Fatal(err)
}
result := esm.ValidateText(string(text))
fmt.Println(result.IsValid)
for _, e := range result.StructuralErrors {
	fmt.Println(e.Code, e.Path)
	fmt.Println(e.Message)
}

From docs/api/examples/go/validate_test.go