N NezamDocumentation

Messages and errors#

User-facing failures must use declared messages. Inline string errors are not acceptable for ERP behavior.

Message declaration#

bl
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.

bl
message vendor_name_required {
  code: "AP-ERR-0001";
  severity: error;
  category: validation;
  message: {
    en: "Vendor name is required.";
  };
}

Severity values are:

SeverityUse
errorOperation cannot continue
warningOperation can continue but needs attention
infoInformational diagnostic

Categories#

Use categories to make failures operationally useful:

CategoryUse
validationCaller supplied invalid or incomplete input
ruleA business rule failed
securityAuthorization or security policy failed
integrityReferential or consistency constraint failed
ioExternal IO or integration failed
performancePerformance guard or budget failed
domainDomain invariant failed
systemPlatform or runtime condition failed
userUser-facing action or state issue
infoInformational 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.

bl
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.

bl
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.

bl
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.

bl
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.

bl
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.

bl
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.

bl
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.

bl
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.

Source: packages/business/language/messages-errors.md