Messages and errors#
User-facing failures must use declared messages. Inline string errors are not acceptable for ERP behavior.
Message declaration#
message posting_policy_required {
code: "FI-ERR-1004";
severity: error;
category: custom("config");
entity PostingPolicy;
params: {
company_code: CompanyCode;
document_type: DocumentType;
};
metadata: {
owner: "finance";
tags: ["configuration", "posting"];
priority: high;
};
message: {
en: "Posting policy is required for the company and document type.";
"ar-SA": "Posting policy is required for the company and document type.";
};
}Messages can have annotations and access modifiers. The body can contain header properties, localized content, typed params, metadata, plural forms, annotations, and entity references.
Header properties#
Header properties are name: value entries. Common headers are code, severity, and category.
message vendor_name_required {
code: "AP-ERR-0001";
severity: error;
category: validation;
message: {
en: "Vendor name is required.";
};
}Severity values are:
| Severity | Use |
|---|---|
error | Operation cannot continue |
warning | Operation can continue but needs attention |
info | Informational diagnostic |
Categories#
Use categories to make failures operationally useful:
| Category | Use |
|---|---|
validation | Caller supplied invalid or incomplete input |
rule | A business rule failed |
security | Authorization or security policy failed |
integrity | Referential or consistency constraint failed |
io | External IO or integration failed |
performance | Performance guard or budget failed |
domain | Domain invariant failed |
system | Platform or runtime condition failed |
user | User-facing action or state issue |
info | Informational message |
custom("config") | Required configuration is missing, inactive, or ambiguous |
custom("policy") | A configured policy blocks the operation |
Use custom("config") for missing or invalid configuration. Use custom("policy") when configuration exists and deliberately blocks the operation.
Params#
Parameters define typed values available for interpolation and tooling.
message posting_policy_ambiguous {
code: "FI-ERR-1005";
severity: error;
category: custom("config");
params: {
company_code: CompanyCode;
document_type: DocumentType;
posting_date: date;
};
message: {
en: "More than one posting policy matches the company, document type, and date.";
};
}Keep params actionable. Include the scope values an operator needs to find the missing, inactive, or ambiguous configuration row.
Localized content#
The message: block maps language keys to string literals. Language keys can be identifiers or string literals.
message approval_required {
code: "AP-ERR-0200";
severity: error;
category: custom("policy");
message: {
en: "Approval is required before posting.";
"ar-SA": "Approval is required before posting.";
};
}Metadata#
Metadata entries can be strings, string arrays, or priorities.
message posting_policy_required {
metadata: {
owner: "finance";
tags: ["posting", "configuration"];
priority: critical;
};
}Priority values are low, medium, high, and critical.
Plural forms#
Plural forms attach localized plural text to a named parameter.
message invoice_line_count_invalid {
code: "AP-ERR-0300";
severity: error;
category: validation;
plural lines: line_count {
en: {
one: "Invoice must contain one line.";
other: "Invoice must contain multiple lines.";
};
};
message: {
en: "Invoice line count is invalid.";
};
}Use plural forms for count-sensitive text. Keep the main message: entry present so callers always have a stable fallback text.
Entity references#
Messages can reference the entity they describe.
message vendor_inactive {
code: "AP-ERR-0400";
severity: error;
category: domain;
entity Vendor;
message: {
en: "Vendor is inactive.";
};
}Entity references help tooling group failures by table or domain object.
Labels#
Labels are localized text catalogs for non-error UI text. Labels can be annotated. In the current grammar, label declarations are module members.
module VendorText {
@ui
label vendor_labels {
vendor_name: {
en: "Vendor name";
"ar-SA": "Vendor name";
};
}
}Use labels for captions and display text. Use messages for failures and operational diagnostics.
Error declarations#
The minimal error declaration form declares a named error type.
error PostingPolicyError;The grammar-backed error declaration is intentionally minimal: error Name; has no body, code, severity, category, params, metadata, or localization. Use message declarations for user-facing failure catalogs.
Message-backed raises are statement syntax and can name a message directly or use the message keyword.
raise message posting_policy_required(company_code_param);
raise posting_policy_required(company_code_param) with {
company_code: company_code_param;
};
throw message posting_policy_required(company_code_param);Use error declarations with Test declarations when you need to assert closed failure paths.
Error quality#
Every failure path should explain the root cause clearly enough for the caller or operator to act. Avoid generic text such as failed or invalid request when a specific declared message is possible.