Skip to main content
Generated from the rslc compiler.

E-LOOKUP-TOTAL

State a lookup’s default in the table. E-LOOKUP-TOTAL guards against a lookup that carries a default value of its own. RSL source spells a lookup one way, lookup!(Table, key, …), which takes keys alone, so rslc check leaves this code unprinted. A table states the row for all other keys with otherwise [cite: …]: { … }. A lookup that can reach a key with a missing row gets E-LOOKUP-GAP.

E-ENTITY-REL

Give each record one enclosing record. A record that contains another is its parent, and the contained record is its child. The check asks that each link runs both ways: the child of a record names that record as its parent. The compiler derives both directions from the field types, so a rater written in current forms keeps them in step. The message appears when a second problem leaves a record with two candidate parents, and it arrives together with the message for that problem. Fix that one and both clear. The words [children] and [parent] in the message are the annotations of an earlier version of RSL. Read them as “contains” and “is contained by”. Example Policy and Branch each contain a Location, so Location has two enclosing records.
Fix Give the second position its own record type, as E-RECORD-POSITION advises. The two types share the same fields.
Other causes An older rater marks a field [parent] and gives it a type other than the enclosing record, such as policy: Option(Policy) [parent]. That rater gets E-RELATION-REMOVED as well: delete the field and read the enclosing record by its name.
bad/rater.rsl
good/rater.rsl

E-AXIS-SUBSET

Give each map key one declaration. A map holds one value for each member of its enum, such as a rate for each coverage. The check asks that exactly one declaration states the value of each key. Earlier versions of RSL built a map from several declarations, each over part of the keys. Two of them could claim the same key, and this message names that key. RSL 0.4 gives a map one declaration, so the message always arrives with E-AXES-REMOVED for the second declaration. One declaration that chooses with match c shows every key’s value in one place, and the compiler checks that each key has an arm. Example The map rate is declared for every Coverage and again for FirstParty, so two declarations claim property.
Fix Write one declaration over the enum and give each key its value in a match c arm. Delete the refined enum once it has become unused.
Other causes The two declarations name different enums, such as rate[c: Coverage] and rate[p: Peril]. That rater gets E-MERGE-FIDELITY as well. Give the second map its own name.
bad/rater.rsl
good/rater.rsl

E-HOLE

Replace a placeholder with a calculation. A placeholder, nl "…", holds a calculation that is still written in plain words. E-HOLE is the code for a value that depends on a placeholder. rslc check reports the placeholder itself, on a line that starts obligation: 25, and leaves E-HOLE unprinted. A placeholder lets you sketch a rater and fill it in step by step. rslc check --allow-incomplete accepts a rater whose only open findings are placeholders. The strict check fails until each one is RSL, and rslc export refuses a rater whose outcomes depend on one. Example The calculation premium is a placeholder that describes the rule in words.
Fix Replace the placeholder with the calculation it describes.
bad/rater.rsl
good/rater.rsl

E-ROUND-INC

Round to a scale and a mode. E-ROUND-INC is reserved for a rounding increment that is malformed, as in the removed form round(x, 0.01). rslc check reports every rounding problem as E-ROUND, and that message gives the current form: round(x, 2, half_up).

E-TABLE-MODE

Declare a table with dims and bands. Earlier versions of RSL declared a table as ( … ) -> { … } with a match: line. A range table matched a number against a pair of minimum and maximum columns. RSL 0.4 has one table form: table dims (key: Type, …) -> { outputs }. In that form each key cell is exact, and a range is a band type declared in Types. IntBands(0, 250000, 1000000..) lists the lower cut of each band, and the CSV holds one row for each cut. With the cuts in the type, the compiler proves that every payroll the rater accepts falls in one band. Example The table PayrollRate uses the removed signature, NumRange and match: range over a minimum and a maximum column.
Fix Declare the bands in Types and key the table with them. Delete the match: and columns: lines, and keep one CSV column that holds each band’s lower cut.
Other causes
  • A table dims table still has a match: line. Delete the line.
  • A table has the ( … ) -> { … } signature with match: specific, or with the match: line left out. Write table dims before the keys.
  • An input or a table key has the type NumRange. Declare an IntBands or DecimalBands type and use it.
  • A columns: entry maps a key to a pair of headers. Map one header that holds the lower cut.
bad/rater.rsl
bad/tables/PayrollRate.csv
good/rater.rsl
good/tables/PayrollRate.csv

E-REQUIRES

Keep exact constraint forms in constraints. An input constraint decides which requests the rater accepts, so the compiler evaluates each one in exact arithmetic. Two forms exist for constraints alone, and this message reports one of them out of place or malformed.
  • N% of x is an exact ratio. It belongs in a refinement, such as where self.subcontracted <= 50% of self.payroll.
  • values: Csv on a numeric type keeps the type’s permitted values in enums/<Type>.csv, under the header value.
A calculation states its arithmetic with ordinary operators and its rounding with round. Example The calculation premium uses the exact ratio 50% of self.payroll.
Fix Write the ratio as a multiplication.
Other causes Each of these concerns a numeric type with values: Csv, such as Limit = Num {precision: int, values: Csv}.
  • The rater’s folder lacks an enums/ folder, or the folder lacks Limit.csv. Add the file.
  • The file is empty, or its header is something other than value. Start the file with the line value.
  • The file has a header and zero values. List at least one value.
  • A cell holds text where a number belongs, or repeats an earlier value. Keep one row for each number.
  • A value has more decimal places than the type’s precision. Match the values to the precision.
  • A value lies outside the range in the type’s where self in […]. Widen the range or remove the value.
  • The type leaves out precision. State one, such as precision: int.
  • values: names something other than Csv. Write values: Csv.
  • The braces state values: twice. Keep one.
  • An input wraps the type, as Option(Limit) or List(Limit). Use the type directly on a single input.
bad/rater.rsl
good/rater.rsl

E-REJECT

A reject needs a code and message. reject("CODE", "message") is a form from earlier versions of RSL, where a calculation refused a request. The check reads its two arguments as text literals. The code starts with a capital letter and continues with capital letters, digits, _ and -. The message holds at least one character. RSL 0.4 removes reject itself, so this message always arrives with a second one for the removed form. In a table’s otherwise: reject(…) that is E-OTHERWISE-REJECT-REMOVED, and inside checked(…) it is E-CHECKED-REMOVED. Fix both at once by stating the rule as a refinement. Example The calculation premium calls reject with a code in lower case.
Fix Delete the rejecting branch and state the rule as a refinement on the input, with a code in capitals.
Other causes
  • The call has one argument, or three: reject takes a code and a message.
  • An argument is a number or a name where the call needs a text literal.
  • The code or the message is the empty text "".
  • A table’s otherwise: reject(…) has a malformed code or an empty message.
  • The third argument of checked(x, T, …) is something other than a reject call.
bad/rater.rsl
good/rater.rsl

E-MERGE-FIDELITY

Declare each map once, over one enum. Earlier versions of RSL built a map from several declarations and merged them. This check confirms that the merged map gives each key the value its own declaration wrote. It reports a key whose owner is ambiguous after the merge. RSL 0.4 gives a map one declaration, so the merge has a single input and the check holds. The message appears when a name is declared as a map twice, over two different enums. It arrives with E-AXES-REMOVED for the second declaration and E-AXIS-SUBSET for the two enums. The numbers in the message are positions in the file and the compiler’s own labels. Read the map’s name and the key, then find the two declarations. Example The step declares rate over Coverage and again over Peril.
Fix Keep one declaration of rate, over one enum. A second map, over another enum, takes its own name.
bad/rater.rsl
good/rater.rsl

E-BAND-COVERAGE

Cover every lookup key with a band. E-BAND-COVERAGE is retired. It was the code for a number that falls outside every band of the band type that keys a table. rslc check reports that problem at the lookup as E-KEY-RANGE, with the range the key can take and the range the bands cover.

E-EXTERN-REMOVED

Declare an external table as an ordinary table. Earlier versions of RSL let a table point at rows held outside the rater, with [extern: "…"] and related annotations. RSL 0.4 keeps every table’s rows in the rater’s own tables/ folder, where the check reads them. With the rows in the folder, the compiler proves that each lookup finds a row. A large table needs the same declaration as a small one, and the compiler chooses how to store it. A lookup by an identifier, such as a class code, keys the table with a Code type. An otherwise row gives the filed rate for every code the table leaves out. Example The table ClassRate carries the removed extern annotation and has its rows outside the rater.
Fix Delete the annotation and save the rows as tables/ClassRate.csv, with one header for each key and each column.
tables/ClassRate.csv
Other causes The annotations implementation, path, sqlite_table and reject on a table also belonged to external tables and get the same message. Delete each one.
bad/rater.rsl
good/rater.rsl
good/tables/ClassRate.csv

E-TEXT-REMOVED

Replace Text with a code or an enum. Earlier versions of RSL had a Text type for free text. In RSL 0.4 the type of every value states what the value accepts, so the compiler can check each rule that reads it. An identifier, such as a class code or a ZIP code, is a Code type with a pattern: ClassCode = Code(pattern: "[0-9]{4}"). A closed set of labels is an enum. A value that rating leaves unread, such as the insured’s name, belongs to the system that calls the rater. A Text input that lacks the [extern] annotation gets E-TYPE as well. One fix clears both messages. Example The input insured_name has the removed type Text, and the premium ignores it.
Fix Delete the input: the premium reads only payroll. Where a rule reads the value, declare its type in Types as a Code with a pattern, or as an enum of its labels.
bad/rater.rsl
good/rater.rsl

E-AXIS-INDEX

Read a map at a key it defines. E-AXIS-INDEX is the code for a read of an indexed value at an element it leaves undefined. An indexed value in RSL 0.4 is a map over an enum, and rslc check reports the same problem as E-MAP-DOMAIN.

E-REQUIRES-REMOVED

Write a record rule as a refinement. A rule that compares two inputs of one record belongs to the record. Earlier versions of RSL wrote such rules in a requires block inside the record. RSL 0.4 writes each rule as a refinement after the record’s closing brace: } where condition. A refinement states which requests the rater accepts. The compiler uses it when it proves each calculation, and a request that breaks the rule is refused before rating starts. The message quotes the first clause of the block as the refinement to write. Example The record Policy states its rule in a requires block.
Fix Delete the block and write its clause after the record’s closing brace. A block with several clauses becomes one where for each clause, written one after another.
bad/rater.rsl
good/rater.rsl

E-RANGE-REMOVED

Write a value range as a refinement. Earlier versions of RSL stated the values a number accepts inside the type’s braces: {precision: int, range: [0, 100]}. RSL 0.4 keeps precision in the braces and writes the range as a refinement after the type: where self in [0, 100]. A refinement is the one place a rater states which values it accepts. The compiler reads it to prove each calculation, and a request outside the range is refused before rating starts. The message gives the refinement to write, with the bounds copied from the old range. Example The input payroll states its range as range: metadata.
Fix Delete range: from the braces and write the bounds as where self in […] after the type. Annotations in brackets, such as a label, stay before the where.
Other causes
  • A type alias in Types states range: metadata. Write the same refinement after the alias’s type.
  • A table column states range: metadata. Delete it: the rows of the table give the column’s values.
bad/rater.rsl
good/rater.rsl

E-AXES-REMOVED

Replace an axis with an enum and maps. Earlier versions of RSL declared coverages, perils and similar dimensions in an Axes block and indexed values by axis. RSL 0.4 uses the forms it has for every other set of labels:
  • The dimension is an enum in Types, such as Coverage.
  • A value for each member is a map with one declaration: rate[c: Coverage].
  • A value that differs by member chooses with match c.
  • A read names one key: self.rate[c] or self.rate[@Coverage.liability].
  • A total names the enum and a binder: sum(Coverage as c, self.rate[c]).
A subset of the members is a refined enum, declared in Types and used in the same places. With one declaration for each map, the compiler proves that every key has a value. Example The total premium folds over an axis with the removed form sum(x over axis).
Fix Name the enum and a binder first, then read the map at the binder.
Other causes
  • The file has an Axes block. Declare each axis as an enum in Types, as Coverage is in the example.
  • A step declares one member of a map, as rate[liability], or a listed subset. Write one declaration over the enum and choose with match c.
  • A step declares the same map twice. Write one declaration over all the keys.
  • A read lists several keys, as self.rate[c: {liability, property}]. Read one key.
  • A table column lists members, as rate: Rate[{liability, property}]. Key the column by the enum: rate: Rate[Coverage].
  • An input carries an axis annotation, as limit: Num [coverage]. Declare one input for each member and build the map in a step.
bad/rater.rsl
good/rater.rsl

E-RELATION-REMOVED

Declare records and contain them by type. Earlier versions of RSL declared Entities and linked them with annotated fields: [children] on the parent and a [parent] field on the child. RSL 0.4 declares Records, and a record contains another by naming its type.
  • A field typed Location holds one record.
  • A field typed Option(Location) holds at most one.
  • A field typed List(Location) holds several.
A contained record reads its ancestor by the record’s name, as Policy.experience_mod. The compiler knows each record’s place from the types, so the back-reference field has gone. Example The file declares Entities, a [children] list of EntityId(Location) and a [parent] field on Location.
Fix Rename the section to Records and type the list List(Location). Delete the [parent] field and read the policy’s value as Policy.experience_mod.
bad/rater.rsl
good/rater.rsl

E-REJECT-REMOVED

State a refusal as an input refinement. Earlier versions of RSL let a calculation refuse a request with reject("CODE", "message"). In RSL 0.4 every calculation returns a value for every request the rater accepts. A rule that refuses a request is a refinement on the inputs it reads. The refinement keeps the business code and the message. A request that breaks the rule gets that code before rating starts, and the calculation holds only arithmetic. The message names the calculation and the kind of rule it found. Its help line writes the refinement, with the code and message copied from the reject. Example The calculation premium refuses a payroll below 1,000 with reject.
Fix Delete the rejecting branch. State the rule where the input is declared, as a range with the code, the message and a citation. The help line shows a second form: a refinement of the whole record, written after its closing brace. Use that form for a rule that reads several inputs.
bad/rater.rsl
good/rater.rsl

E-OTHERWISE-REJECT-REMOVED

Refuse an unrated key at the input. Earlier versions of RSL let a table refuse a key that lacks a row, with otherwise: reject("CODE", "message"). In RSL 0.4 a lookup returns a row for every request the rater accepts. A rule that refuses a request is a refinement on the input it reads. The refinement keeps the business code. A request with an unrated key gets that code before rating starts, and the compiler proves that each lookup finds a row. otherwise remains for the filed all-other row, written with values and a citation: otherwise [cite: manual:p4]: { rate: 3.1 }. Example The table TerritoryRate files rates for urban and rural, and refuses offshore with otherwise: reject.
Fix Delete the clause and narrow the input that the lookup reads, with the code, the message and a citation. Where the filing prints a rate for all other keys, write that row as otherwise [cite: …]: { … }.
bad/rater.rsl
bad/tables/TerritoryRate.csv
good/rater.rsl
good/tables/TerritoryRate.csv

E-CHECKED-REMOVED

Prove a range from the inputs. Earlier versions of RSL tested a value against a type while rating: checked(x, T, reject("CODE", "message")) refused a request whose x fell outside T. In RSL 0.4 every calculation returns a value for every request the rater accepts. The compiler proves that x lies in T from the ranges of the inputs. A rule that refuses a request is a refinement on the input it reads. The refinement keeps the business code, and a request outside the range gets that code before rating starts. Example The calculation rated_payroll tests the payroll against the type RatedPayroll with checked.
Fix Narrow the input to the range of the type, with the code, the message and a citation. Then read the input directly: the compiler proves the range. Where the filing caps the value, write the cap as arithmetic, such as max(min(self.payroll, 100000000), 1000).
bad/rater.rsl
good/rater.rsl

E-SLOT-REMOVED

Let the formula state the rule. Earlier versions of RSL let the brackets of a calculation repeat what its formula does, in keys such as at_least:, total: and chain:. The compiler reads the same facts from the formula, so RSL 0.4 writes each rule once. One statement of a rule stays true when the formula changes. A key beside the formula could say one thing while the arithmetic did another. The message names the key, and its help line says which part of the formula carries the meaning. Example The calculation premium applies a minimum with max(…) and repeats it as at_least: minimum_premium.
Fix Delete the key. The max(…) in the formula states the minimum.
Other causes Eleven keys get this message. Delete each one; the list says what states the rule in its place.
  • at_least: is stated by max(…) in the formula.
  • at_most: is stated by min(…) in the formula.
  • total: is stated by the sum in the formula.
  • product: and chain: are stated by the product in the formula.
  • by: is stated by the keys of the lookup.
  • selects: is stated by the inputs the calculation reads.
  • series: is stated by a map value that reads its own previous element.
  • bands: becomes a group: write collect and a title.
  • when: becomes a condition: write exception when … or with … otherwise.
  • within: becomes a choice: write select(low..high, position).
bad/rater.rsl
good/rater.rsl

E-INVARIANT

Meet each structural rule of a rater. E-INVARIANT is reserved for a rater that breaks one of the compiler’s numbered structural rules. rslc check prints such a finding on a line of its own. The line starts with the kind of finding and the rule’s number, in place of an E- code. A placeholder, nl "…", is one such case: its line starts obligation: 25.