Finding catalogue
Every rule this build can report, by code.
The code is the identity. It is stable, it is what a test asserts on, and
it is what dbml-sharepoint explain takes. The message printed beside a
finding is prose for a human and may be reworded in any release, so nothing
should match on it.
A code names what is wrong, not where. The section, entity, view and
column are carried on the finding's location, which is normally the dotted
path the message opens with. Two rules that produce the same sentence for
different reasons therefore get two codes, and one rule reachable from two
sections keeps one.
Codes beginning condition_ come from the shared condition grammar and can be
raised from any section that accepts a when: views, form_visibility,
column_validation and list_validation alike.
Look one up without leaving the terminal:
dbml-sharepoint explain unknown_column_type
| Code | Severity | What it means |
|---|---|---|
all_items_view_declared | error | A view named All Items is declared; that view is generated with every rendered column and no filter, and cannot be overridden. |
attachments_on_document_library | error | attachments: false is declared beside an entity of kind: DocumentLibrary. The deploy would write EnableAttachments = false on every list it provisions, and a library refuses a write to that property. Measured 2026-09-06 by library.doc-lib.attachments-sticks in the list-settings probe: writing EnableAttachments = true to a scratch document library came back HTTP 500, -2146232832, Microsoft.SharePoint.SPException, "Attachments are not allowed for Document libraries and Surveys", and the flag still read back false. The list side of the same run settled the other way (wrote false over true, read back false). So a library reaching the deploy would stop the paste at that list rather than accept the write silently, and this refusal turns that into a build message. |
auto_increment_pk_must_be_id | error | An auto-increment primary key is named something other than Id. |
automation_group_granted_full_control | error | A group enrolling automation, or named dbml Automation Accounts, is granted Full Control, on the default policy or on an override. dbml Automation Accounts exists so the identity a flow connects as can hold a narrow declared write on the lists it stamps: under reconcile: exact a redeploy removes undeclared direct grants, so access handed to a flow by hand does not survive one and the identity has to sit in a group the mapping declares, holding a level it declares. Full Control is what dbml List Administrators already carries on every list, so granting it here gives the automation the breadth the group was declared to avoid, and the name goes on saying otherwise. Grant the narrowest level that lets the flow write. Only Full Control is refused; which narrower level an automation needs is the mapping's call. The built-in names are English, so on a non-English tenant the equivalent level is spelled otherwise and is not matched, the same blind spot enterprise_reader_group_over_privileged carries. |
blank_key_took_default | warning | A key is written with no value, so the loader read it as absent and gave it its default, and that default decides how the deployed lists behave: a boolean, a vocabulary word such as direction or reconcile, a where or when condition, a from_enum source, major_version_limit, a view's row_limit, an entity's title, the default permission policy's site_role or a policy's assignments. The author may have meant a value. Remove the key to take the default without this warning, or give it a value. A blank key whose default is empty text, an empty list or no value is not reported. |
calculated_column_has_no_formula | error | A calculated_* DBML column has no matching entry under calculated_formulas:. |
calculated_display_column_unindexable | warning | A lookup target's display column is calculated, and calculated columns cannot be indexed, so its picker stops working once the list passes roughly 5,000 items. |
calculated_formula_cycle | error | Calculated columns on one entity depend on each other in a cycle, so no creation order can satisfy them. |
calculated_formula_deferred_lookup | error | A calculated formula references a lookup the deploy defers to Phase 2. The calculated field is created in Phase 1, before that column exists. |
calculated_formula_missing_equals | error | A calculated formula does not start with =. |
calculated_formula_references_a_retired_column | error | A live calculated formula references a column that has been retired. |
calculated_formula_self_reference | error | A calculated formula references its own column. |
calculated_formula_too_long | error | A calculated formula is longer than SharePoint's limit. |
calculated_formula_unknown_column | error | A calculated formula references a column that is not rendered. SharePoint resolves references when the field is created and rejects the POST on any miss. |
calculated_formula_unsupported_operand | error | A calculated formula references a Lookup, Person, multi-line- text, rich-text or Hyperlink column. Measured against a live site: SharePoint refuses all five when the field is created. |
color_by_map_key_not_in_enum | error | A data-bar color_by map names a choice the source column's enum does not contain. |
column_collides_with_report_column | error | A declared column reaches the report under a name the pack itself adds, such as ItemURL. The query then selects the column and adds its own of the same name, which fails the refresh rather than the build. Rename the schema column. |
column_name_too_long | error | A column's internal name exceeds SharePoint's length limit. |
column_not_rendered | error | A form_visibility or column_validation entry names a column the list does not render. |
column_validation_missing_a_blank_arm | error | A column validation on a NULLABLE column compares the value against something without saying what a blank does. Whether SharePoint refuses a blank operand or ignores the rule is unmeasured, so the guarded spelling is the only one that behaves the same either way: wrap the comparison in any_of with an is_null test on the same column, or make the column not null if a value was always meant to be required. A rule that compares a date with today or a datetime with now does not need this -- the build hoists it onto the list rule and guards it there (see analysis/save_rules.py). |
column_validation_on_a_boolean_column | error | A column_validation rule is declared on a Yes/No column. SharePoint refuses a validation formula on that field type (field.client-validation.boolean-server-only), so the deploy would abort at the field it names. Use list_validation for the rule, or move the column off boolean. |
column_validation_on_a_retired_column | error | A save rule sits on a retired column. Retirement hides it from the New form, so the rule cannot be satisfied there and would reject every new item. |
column_validation_references_other_columns | error | A column validation formula references a column other than its own; SharePoint permits only the column being validated. |
composite_index_unsupported | error | A DBML indexes { } entry names more than one column; the deployer can represent only a one-column index. |
condition_choice_member_unknown | error | A whole-member Choice comparison does not use the exact spelling of a member declared by the column's DBML enum. |
condition_column_type_unknown | error | A leaf names a column with no declared type, so the literal cannot be typed. |
condition_date_is_an_unquoted_yaml_datetime | error | An unquoted YAML datetime reaches the renderers with a SPACE separating date from time, a spelling no probe has run. Quote it. |
condition_date_unparseable | error | A date column's literal is neither a date nor a today/now sentinel. |
condition_date_wears_whitespace | error | A date literal carries surrounding whitespace, which every renderer would emit unchanged. |
condition_field_not_rendered | error | A leaf names a column the list does not render. |
condition_lookup_unsupported_by_target | error | A validation formula cannot read a lookup column. |
condition_me_operator_meaningless | error | me is an identity, so only eq/neq mean anything against it. |
condition_me_takes_no_property | error | me compares the person column's user id, so it takes no accessor. |
condition_me_unsupported_by_target | error | The me sentinel has no verified client-side equivalent for show/hide. |
condition_measure_not_applicable | error | measure: length was applied to a column that is not text. |
condition_measure_unknown | error | A measure other than length was declared. |
condition_measure_unrenderable | error | The target cannot express a measure at all. CAML has no LEN, and list formatting's length() does not measure a string. |
condition_needle_empty | error | A substring or membership operator was given an empty value, which cannot discriminate. contains matches every value that way, and includes on a multi-value column matches none, leaving a view that is empty forever. |
condition_negation_unrenderable | error | Negating the rule, as none_of does, produces an operator the target cannot express. |
condition_negative_text_operator_unrenderable | error | CAML has no <Not>, <NotContains> or <NotBeginsWith>, so a view filter cannot say "does not contain". |
condition_now_on_a_date_column | error | The now sentinel needs a datetime column; a date column has no time of day. |
condition_now_unsupported_by_target | error | The now sentinel has no verified client-side equivalent for show/hide. |
condition_operand_type_unsupported | error | The target refuses this operand type outright: a person, multi-line, hyperlink or calculated column. |
condition_operator_not_negatable | error | none_of met an operator with no declared inverse, so it cannot be pushed down to the leaves. |
condition_operator_unknown | error | The declared operator is not in the grammar. |
condition_operator_unrenderable | error | The operator is in the grammar but the target has no spelling for it. |
condition_operator_unverified | error | The operator is plausible from the documented syntax but has not been watched on a live tenant for this target. |
condition_property_not_applicable | error | An accessor was declared on a column that is neither a person nor a lookup. |
condition_property_required | error | A person or lookup column needs an accessor; there is no defensible default between a name, an email and an id. |
condition_property_unknown | error | The accessor is not one this column kind offers. |
condition_property_unrenderable | error | The target cannot reach person or lookup sub-properties at all. |
condition_reads_the_formula_clock | warning | today+N or today-N compared on a datetime column in a validation rule renders TODAY()+N or TODAY()-N, and that clock was measured 16 to 20 hours behind the site (2026-09-02), so the window lands hours away from where it reads; now compares with the instant of the save exactly. |
condition_sentinel_with_a_substring_operator | error | A today/now sentinel was combined with a substring test, which would search for the sentinel's own spelling. |
condition_set_empty | error | in/not_in was given an empty list, which is a constant rather than a condition. |
condition_substring_test_on_a_non_text_column | error | A substring operator was applied to a boolean, number, date or person column. |
condition_today_on_a_datetime_column | error | A bare today compared on a datetime column in a validation rule would read TODAY(), a clock measured 16 to 20 hours behind the site (2026-09-02); say now, which compares with the instant of the save. |
condition_today_unsupported_by_target | error | The today sentinel has no verified client-side equivalent for show/hide. |
condition_too_deep | error | The condition nests more groups than the depth cap allows. |
condition_too_many_leaves | error | The condition expands past the leaf cap once in lists are counted out. |
condition_value_has_a_control_character | error | The value contains a character XML forbids, which no escaping can carry. |
condition_value_missing | error | The operator needs a value and none was declared. |
condition_value_not_a_boolean | error | A boolean column's operand is neither truthy nor falsy under the two-sided coercion. |
condition_value_not_a_list | error | in/not_in needs a list. |
condition_value_not_a_number | error | A numeric column's operand is not a number. |
condition_value_not_allowed | error | is_null/is_not_null take no value. |
condition_value_not_finite | error | A numeric operand is an infinity or a NaN. |
condition_value_not_text | error | A condition compares a text column with a value that is not a string. It renders as str(value), so an unquoted 0800 compares as "800"; quote the value. |
configured_break_grants_nothing | warning | A list_permissions policy (the default, an override or a folder policy) declares reconcile: configured, break_inheritance: true and no assignments. On a scope that still inherits, the deploy's ACL phase breaks inheritance with copyRoleAssignments=false, grants nothing, and removes nothing, because configured mode removes only a level a declared principal holds. test/manual/operator-safety-grant-probe.js measured that break on a list leaving exactly one binding, the running account's own at Full Control, so every other principal that held a role through inheritance loses it. It is not measured for an operator who is not a site collection administrator, nor on a folder; the list measurement is the evidence here. On a scope that already has permissions of its own, the policy writes nothing. A folder policy under a library that reconciles exact is refused by folder_policy_manages_nothing instead. This is a warning rather than an error because breaking a scope to manage it by hand is a legitimate intent. Declare the assignments the scope should have, or set break_inheritance: false if it should keep inheriting. |
cross_site_column_cannot_be_unique | error | A cross-site reference column is marked [unique]. Its logical column is replaced by generated Abbreviation and SiteUrl fields, so the constraint would never be deployed. |
cross_site_column_has_no_ref | error | A cross_site_reference_columns: entry names a column with no DBML ref:. |
cross_site_expansion_unhandled | error | A cross-site reference column needs an extension that expands it; the active one deferred. |
cross_site_generated_name_collides | error | A cross-site column's generated companion field has the same name as a column the DBML already declares. |
cross_site_generated_name_too_long | error | A cross-site column's generated Abbreviation or SiteUrl field exceeds SharePoint's 32-character internal-name limit. |
cross_site_unknown_column | error | A cross_site_reference_columns: entry names a column the entity's table does not declare. |
default_formula_beside_a_default_value | error | A column carries a default formula in the mapping and a default: in the DBML. Nothing has measured which one SharePoint honours when a field has both, so a column declares one or the other. |
default_formula_choice_result_unchecked | warning | A default formula on a single-value enum column must produce a member of the enum at run time, and the build cannot evaluate the clock to check it. Measured 2026-09-13 (library-guards-probe.js c445a55c, field.default-formula.choice-non-member-result): a Choice formula whose result was not a member stored the literal Q13. The field is not left blank; it holds a value outside the choice set. |
default_formula_column_kind_unsupported | error | A default formula is declared on a column kind that cannot take one: the built-in Title, a calculated, multi-value, Person, Hyperlink or Lookup column, or a cross-site reference column. |
default_formula_function_unsupported | error | A default formula calls a function outside the allowed set (TODAY, YEAR, MONTH, DAY, ROUNDUP, ROUNDDOWN, MOD, TEXT, IF, AND, OR, with the & operator), each of which filled a column on a live site on 2026-09-13. Names are matched as spelled; nothing has measured what SharePoint does with any other. |
default_formula_missing_equals | error | A default formula does not start with =. |
default_formula_references_a_column | error | A default formula names a column in square brackets. It runs before the row exists, so there is no column to read; compute from TODAY() and constants. |
default_formula_type_unsupported | error | A default formula is declared on a column type it is not supported on. Supported: date, datetime, int, number, nvarchar and a single-value enum, each measured on a live site (date through field.date.dynamic-default-rest-fill; the rest through library-guards-probe.js c445a55c on 2026-09-13). |
default_formula_unknown_column | error | A default formula names a column the deploy does not create on that entity. |
default_not_an_enum_member | error | A column's default is not a member of the enum it is typed as. |
default_view_hidden | error | A view is both default: true and hidden: true. Hiding the current default view is not measured to work, so declare one or the other. |
demo_boolean_value_invalid | error | A demo row's value for a Yes/No column is not a YAML boolean. An unquoted no is the text "no" under YAML 1.2. |
demo_column_not_writable | error | A demo row writes a column the deploy does not create, or writes Id. |
demo_date_value_invalid | error | A demo row's date value is neither today+N/today-N nor a real ISO calendar date. |
demo_enum_value_unknown | error | A demo row's value is not a member of the column's enum. |
demo_file_folder_undeclared | error | A demo file names a folder the library does not declare in entities.<name>.folders. The folder phase creates only declared folders, so the upload would have nowhere to go. |
demo_file_name_invalid | error | A demo file's name breaks one of Microsoft's file and folder name rules, or the two this tool adds: it contains one of `" * : < > ? / \ |
demo_file_name_missing_marker | error | A demo file's name does not start with [DEMO] . On a library the file name is what every view and the file panel show, so it carries the sample-data notice a list row carries in its Title. |
demo_file_on_a_list | error | A demo row declares file on an entity that is not a DocumentLibrary. A list row is created with a POST to /items and has nowhere to put a file. |
demo_file_required_on_library | error | A demo row on a DocumentLibrary declares no file. A library's items are files: a POST to /items is refused outright (measured 2026-07-29), so the seeding script uploads the declared file and then sets the row's values on it. Declare file: { name, folder, content }. |
demo_hyperlink_address_invalid | error | A demo row's hyperlink address is not a non-empty string. Checked as a string, not stringified -- str(None) is "None", which would deploy as a link pointing at the word None. |
demo_hyperlink_object_invalid | error | A demo row's hyperlink object value is not {url: <address>, description: <label>} with description optional. |
demo_multi_value_duplicate_member | error | A demo row repeats a member within one multi-value value. The write shape measured as M3 on 2026-08-17 is a collection of choices, and nothing has measured what a repeated member reads back as, so the row is refused rather than seeded into an unmeasured state. |
demo_multi_value_not_a_list | error | A demo row writes a multi-value column with a scalar. The write shape is a collection, so the value has to be authored as a list. An empty list is accepted and leaves the column unset. |
demo_number_value_invalid | error | A demo row's value for a number column is not an int or float (a boolean does not count). |
demo_object_value_invalid | error | A demo row's object value is not exactly {demo_ref: <key>}. |
demo_person_value_unsupported | error | A demo row writes a person column with something other than "@me", the deploying operator. |
demo_ref_forward_reference | error | A self-referencing demo row's demo_ref names a row declared at or after it, so the target does not exist when the row is written. |
demo_ref_on_non_lookup | error | A demo row uses demo_ref on a column that is not a lookup. |
demo_ref_target_mismatch | error | A demo row's demo_ref resolves to a row of a different entity from the one the lookup targets. |
demo_ref_unknown_key | error | A demo row's demo_ref names a key no demo row declares. |
demo_text_value_invalid | error | A demo row's value for a text column is not a string. An unquoted 0800 is the int 800 under YAML 1.2, so quote it. |
demo_title_missing_marker | error | A demo row's Title does not start with [DEMO] , the visible notice used to identify declared sample data. Rollback requires per-list confirmation before every delete. |
demo_value_on_calculated_column | error | A demo row writes a calculated column. Set its inputs instead. |
deprecated_enrolment_flag | warning | A group uses enroll_enterprise_reader: true or enroll_operator_during_deploy: true. Both still load: the first as enroll: [enterprise_reader] with membership: exclusive, the second as enroll_during_run: [operator]. Move to the new keys; the flags will be removed in a later release. |
derived_count_bad_source | error | A derived count names a child entity that is not in the schema, or a via column on that child which does not point back at the entity being counted for. |
derived_lookup_bad_target | error | A derived lookup names a via column that is not a lookup, one that points at a different entity than from, or a target that is not reported beside this list so no key into it exists. |
derived_name_collides | error | A derived reporting column takes a name the list's report query already produces. The column is added rather than overwritten, so the refresh fails; replace: true is how a column already there is computed over. |
derived_unknown_entity | error | A derived_columns: entry names an entity the schema does not declare. |
derived_unknown_reference | error | A derived reporting column reads a column that its source does not carry. Nothing between the build and Power BI reads these names, so an unresolved one is a refresh failure after publication rather than a build failure. Names are the internal ones the schema declares, not the display titles the model shows. Another list is read as it is fetched, keys included and reporting-only columns excluded, because reading those would make the two queries name each other, a cyclic reference at refresh. This list's own rows are read as the entries above have left them. |
display_column_not_rendered | error | A lookup target's display_column names a column the deploy never creates, so the automatic index would be created on a field that does not exist. |
display_column_type_unindexable | error | A lookup target's display_column is a type SharePoint cannot index. The deploy sets Indexed=true, reads it back and aborts part-way through when it did not stick. |
display_title_collides_with_report_column | error | A column's resolved display title is one of the columns the reporting pack adds to the same list: Site Url, Site Name, List Title, <Entity> Key, or, with reporting.system_columns on, Created By Id, Created By Title, Created, Modified By Id, Modified By Title and Modified. The generated Power Query adds those columns and THEN runs Table.RenameColumns to give every schema column its display title. Renaming a column onto a name the table already carries is an error in M, so this does not produce a wrong report -- it produces a refresh that fails, after the model has been published. display_name_mode: auto reaches it with no override written at all, because the auto-split turns SiteUrl into Site Url, SiteName into Site Name and ListTitle into List Title. Give the column a different display title, or rename the schema column so the auto-split lands somewhere else. |
display_title_too_long | error | A display title exceeds SharePoint's 255-character bound. |
duplicate_column_name | error | A table declares the same column name twice. |
duplicate_demo_key | error | Two demo rows share a key. Keys are global across entities because demo_ref resolves against all of them. |
duplicate_display_title | error | Two columns of one entity resolve to the same display title, making them indistinguishable on every form and view. |
duplicate_enum_member | error | One enum declares the same member twice. The members reach the deploy body as an ordered Choices collection, and the field reconciler compares that collection index by index, so a repeat can leave the reconciler unable to converge. It applies to every enum, not only the ones backing a multi-value column. |
duplicate_enum_name | error | Two enums share a name. |
duplicate_folder | error | A library's folders names the same folder twice. Names are compared without regard to case, because a folder is addressed by URL and SharePoint resolves that without regard to case. |
duplicate_group_name | error | Two groups entries share a name case-insensitively, which SharePoint resolves to one group. |
duplicate_index_target | error | One table's indexes { } names the same column twice. |
duplicate_permission_level_name | error | Two permission_levels entries share a name case- insensitively, which SharePoint resolves to one level. |
duplicate_table_name | error | Two tables share a name. |
duplicate_view_title | error | Two views on one entity share a title, or differ only in case -- SharePoint treats those as one view. |
duplicate_view_url_slug | error | Two view titles collapse to the same .aspx URL slug, so the two view pages would fight over one page. |
empty_display_title | error | A display-name override resolves to an empty title. |
empty_enum | warning | An enum declares no members. |
empty_previous_title | error | A renamed_from entry is blank. |
empty_view_url_slug | error | A view title yields an empty URL slug; it needs at least one letter or digit. |
enrolling_group_requires_empty | error | A group declares enroll: and require_empty_at_deploy. The empty gate runs in the security phase, before identity enrolment, and an enrolled account stays, so the second deploy always aborts. Drop one. |
enrolment_declared_twice | error | A group enrols one identity through an old flag and the new key at once. Keep the new key and drop the flag, so one declaration says who the group holds. |
enterprise_reader_group_members_may_edit_membership | error | A group declares both enroll: [enterprise_reader] and allow_members_edit_membership: true. The security phase applies that setting before Phase 1.6 enrols the reader, so the enrolled account can then add principals to its own group -- and everything it adds inherits the group's Read. The exclusivity check reads membership at enrolment time and would find the named reader and pass, so a later addition is never noticed. The one-account promise the manifest prints would hold for one run and be unenforceable afterwards, which is worse than not making it. Drop the setting, or use a different group for the reader. |
enterprise_reader_group_not_exclusive | error | A group enrols enterprise_reader without membership: exclusive. Exclusive is what makes the deploy refuse a group already holding someone else, so a second account cannot share the reader's Read without a person deciding it. The old enroll_enterprise_reader: true loads as exclusive unless membership says otherwise. |
enterprise_reader_group_not_granted | error | A group enrolling enterprise_reader holds no role assignment, so enrolling an account into it grants nothing. The deploy would still report success and the account would see no rows. Grant it Read under list_permissions. |
enterprise_reader_group_over_privileged | error | A group enrolling enterprise_reader is granted something other than the built-in Read. Anything wider contradicts the name. Restricted Read is refused too, and that half is deliberate: Microsoft Learn's site-permissions table shows it lacks Use Remote Interfaces, which an API client needs, so it would be less privilege AND a reporting connector that cannot read anything. |
enterprise_reader_on_trimmed_list | warning | A group enrolling enterprise_reader holds the built-in Read while item_security trims reads to the caller's own items. Read then reaches only the rows the reporting account itself created, and a reporting account writes nothing, so it reads nothing. The deploy still reports success, which is why this is raised at build time. Either drop the read trimming or grant the reader a level that clears it -- and measure which levels do on the tenant you are deploying to, because that is not established here. |
entity_has_no_note | error | A table has no Note:, so the list it provisions deploys with a Description holding nothing but the provenance marker. Fleet reporting can still find the list, but nobody opening it in SharePoint is told what it is for -- and the Description is the only list-level sentence this tool writes, so there is nowhere else for that to come from. Add a Note: to the table saying what the list holds and who it is for. |
entity_kind_template_mismatch | error | An entity's kind and base_template name different containers: List provisions BaseTemplate 100 and DocumentLibrary 101. The create call sends the number and never the kind, so a mismatch provisions one container while every other phase assumes the other. |
entity_not_in_schema | error | The mapping's entities: declares a name the DBML schema has no table for. |
entity_note_too_long_for_marker | error | A table's Note: is long enough that the provenance marker appended after it would not fit in a SharePoint list Description. The marker is what fleet reporting discovers the list by, so it is never truncated -- the note is refused instead. Shorten the note. The budget is deliberately smaller than the space the marker actually leaves: 23 characters are held back so that the marker can grow -- gaining a version suffix, or naming a longer family -- without invalidating notes already written. So a note measured against the marker you can see will be refused while still appearing to fit; the budget the finding reports is the real limit. |
entity_note_whitespace_unmeasured | error | A table's Note: contains a run of whitespace holding a tab, a non-breaking space or another character that is not a plain space. The deploy writes the note as the list Description, reads it back and compares byte for byte, so a character SharePoint normalises aborts every paste after a partial deployment. Two ASCII spaces were measured on 2026-08-14 by test/manual/list-description-probe.js and are preserved, which is why runs of plain spaces are allowed. These other characters were never sent. Use single spaces between words, or plain spaces if you meant alignment. A single tab is not refused, because the wider rule this narrows did not refuse one either. |
enum_members_differ | error | A DBML enum's members differ from the choices configured for it in enum_sources. |
enum_source_has_no_dbml_enum | warning | A configured enum_sources entry has no matching DBML enum in the schema. |
exact_policy_grants_nothing | warning | A list_permissions policy (the default, an override or a folder policy) declares reconcile: exact and no assignments. Exact mode treats the declared assignments as an allowlist, so the deploy's ACL phase issues a removal for every direct role assignment on each scope the policy governs, whoever holds it, and skips only a binding named Limited Access. The operator's own binding is not skipped. Breaking inheritance with copyRoleAssignments=false was measured on a list to leave exactly one binding, the deploying account's own at Full Control (2026-09-22, test/manual/operator-safety-grant-probe.js), so on a list this deploy breaks, the one removal it issues is for the last binding the list holds. That probe granted another principal before removing the operator's binding, so what follows has not been measured on a live site: whether SharePoint accepts the removal of the last binding on a scope, whether an operator who is not a site collection administrator can issue the remaining removals once its own binding is gone, what access the operator keeps, and whether the deploy's read-back of the scope succeeds. That is tracked on #667. This is a warning rather than an error because stripping a scope is supported. Declare the assignments that should stay, or use reconcile: configured, which leaves undeclared grants alone. |
exclusive_group_enrols_a_group_kind | error | An exclusive group enrols an identity whose kinds include security_group or m365_group. Exclusive asserts the group holds nobody else, and the deploy reads a site group's members, not an Entra group's, so the assertion could not be checked. Use an additive group, or restrict the identity to kinds: [user]. |
exclusive_group_enrols_nobody | error | A group says membership: exclusive but has no enroll:. Exclusive describes who the declared identities are allowed to share the group with; to require an empty group, use require_empty_at_deploy. |
exclusive_group_enrols_the_operator | error | An exclusive group also has enroll_during_run: [operator]. Phase 1.5 adds the operator before Phase 1.6 reads the membership, so the exclusive check finds an extra member and aborts every run. Give the operator a group of its own. |
extension_reported | error | A finding raised by an extension's own validators. |
extension_warning | warning | A non-blocking finding raised by an extension's own validators. The error-severity twin is extension_reported. |
field_set_empty | error | A field set declares no columns. |
field_set_name_has_marker | error | A field set's name contains @, which is the marker a view's fields uses to reference a set. |
field_set_unreferenced | warning | A field set is declared but no view on that entity expands it. |
file_scopes_external_needs_library | error | file_scopes: external reaches a list that is not a DocumentLibrary, through list_permissions.default or an overrides entry. external lets a unique scope on a row that reads back as a file (FileSystemObjectType 0) pass the exact-mode descendant check. Learn's FileSystemObjectType enumeration lists Invalid, File, Folder and Web, and does not say what an ordinary list item reads back as, so on such a list the deploy cannot tell a file scope from an item scope. It keeps refuse there, and the setting would do nothing. Set external only on an overrides entry for a document library, or remove it. |
folder_enum_not_a_column_type | warning | A library's folders: {from_enum: <name>} names an enum that no column on that entity uses. That is legal, and folders keyed by something the library does not store are a reasonable design, but it is also what a name that matches a DIFFERENT enum looks like: the build finds the enum, the folders resolve, and every folder is the wrong one. Check the enum against the column the folders are meant to follow, usually the Choice column a file's row carries. |
folder_enum_unknown | error | A library's folders: {from_enum: <name>} names an enum the DBML does not declare. The folders are the enum's members, so there is nothing to create. Check the spelling against the schema's Enum blocks, or write the folder names out as a list. |
folder_name_invalid | error | A declared folder name breaks one of Microsoft's file and folder name rules, or the two this tool adds: it contains one of `" * : < > ? / \ |
folder_permissions_on_a_list | error | list_permissions.folders names an entity that is not a DocumentLibrary. A folder-scoped ACL is written against the folder's list item, and a list has no folders to write one on. |
folder_permissions_without_folders | error | list_permissions.folders names a library that declares no folders, so the policy applies to nothing and the deploy writes no folder ACL at all. Declare the folders on the entity, or remove the block: a policy that silently governs nothing is the failure this rule exists to make loud. |
folder_policy_manages_nothing | error | A list_permissions.folders policy reconciles configured (the default) and declares no assignments, on a library whose own list policy (its override, or the default where it applies) reconciles exact. Configured mode adds the declared grants and removes only a level that a declared principal holds and the policy no longer names, so this policy grants nothing and removes nothing on those folders. break_inheritance: true does not change that on a folder that already has permissions of its own: the deploy breaks inheritance only on a scope that still inherits, so on such a folder it writes nothing at all. Declaring the policy still has an effect. The list's reconcile: exact policy makes the ACL phase stop before writing that list's permissions when a folder or item carries permissions of its own that the mapping does not declare, and a declared folder is exempt. This policy therefore switches that check off for every folder it covers without managing any of them, so a folder somebody secured by hand passes unreviewed. Declare the assignments the folders should have, or use reconcile: exact so every grant on them is reviewed. The rule applies only under an exact list because the check runs only when the list or a folder policy reconciles exact, and a library has one folder policy. Under a configured list, or a library with no list policy, there is no check to exempt a folder from, and a configured folder policy that only breaks inheritance is a legitimate way to hand the folders to manual management. |
folders_on_a_list | error | folders is declared on an entity that is not a DocumentLibrary. Only a library holds folders; the folder phase creates each one under the library's root folder and reads it back, and a list has no root folder to create under. |
form_columns_in_no_section | warning | Columns are referenced by no form body section. SharePoint appends them to the last section, so the form still renders -- but the declared arrangement stops being the deployed one. |
form_part_references_calculated_column | error | A form header or footer references a calculated column. Calculated columns resolve to an empty string there, so the part renders blank with no error anywhere. |
form_section_entirely_hidden | error | Every column in a form body section is declared new: false and existing: false, so the section renders as a bare heading. Not asserted of the last section, which is SharePoint's documented catch-all. |
form_section_field_not_rendered | error | A form body section names a field the entity does not render. |
form_visibility_condition_unreachable | error | A column is hidden on every form yet carries a when, which can never be reached. |
form_visibility_on_a_calculated_column | error | A calculated column declares form visibility. Calculated columns never appear on an entry form. |
formatter_column_not_rendered | error | A column_formatting: entry targets a column that does not receive formatter updates. Only primary deployed fields accept formatters; generated lookup projections and view-only fields may be referenced by a formatter but cannot be its target. |
formatter_field_not_displayed | error | A row or displayed column formatter references a real column the view does not display; a formatter can only read columns in its own fields, so the format would never fire. |
formatter_field_not_rendered | error | A view formatter references a column the entity does not render. |
formatter_missing_elmtype | error | A column formatter's JSON has no root elmType, so it is not a SharePoint column-formatting object. |
formula_target_not_calculated | error | A calculated_formulas: entry names a column whose DBML type is not one of: calculated_date, calculated_number, calculated_text. |
governance_retention_conflicts_with_default | error | A list's governance retention names a different policy than the one list_defaults in the retention policies file sets for that list, keyed by entity name or prefixed title. Make the two agree. |
governance_unknown_column | error | A governance.lists.<Entity>.columns key names a column the DBML does not declare for that table. A retired column is still declared, so it is accepted; a name that was never declared is not. |
governance_unknown_entity | error | A governance.lists key names a table the schema does not declare, or one the mapping's entities: does not deploy. Governance describes deployed lists only; fix the name or declare the entity. |
governance_unknown_retention_policy | error | A governance retention value names a policy that the file named by retention_policies_source does not define, or the mapping names no such file. |
governance_value_outside_vocabulary | error | A governance owner, classification or personal_data value is not in the matching list under governance.vocabulary. Values are compared exactly, and a mapping that declares no vocabulary can use no values. |
group_auto_accept_without_requests | error | A groups: entry sets auto_accept_request_to_join_leave while allow_request_to_join_leave is false. A group cannot auto-accept join requests it does not accept, and SharePoint does not refuse the combination -- MEASURED 2026-08-13 and again 2026-08-14 against a live tenant, it answers HTTP 200 and then stores auto-accept as FALSE. The deploy would report the group reconciled while the site quietly disagreed with the mapping, and nothing reads those flags back to notice. Set allow_request_to_join_leave: true as well if you meant the auto-accept, or drop it. |
group_description_too_long | error | A groups: entry's description is longer than 512 characters. MEASURED 2026-08-13 against a live tenant: SharePoint answers a longer one with HTTP 500 and the message "The parameter Description cannot be null or bigger than 512 characters." It REFUSES rather than truncating, and it does so in deploy phase 1.3, part-way through writing site groups and before any list exists -- so the run stops against a half-provisioned site. Shorten the description. Note the same run found that a group description otherwise round-trips byte-identically, including an ampersand and a run of two spaces: the restrictions a LIST note carries do not apply here, because SP.Group.Description is a different surface and was measured on its own. |
group_description_too_long_for_marker | error | A groups: entry's description leaves no room for the provenance marker appended to it. The deploy stamps every group it writes with Provisioned by dbml-sharepoint, and the adoption gate refuses to adopt a group whose description does not carry it, so a truncated marker would make the tool refuse a group it created itself. Shorten the description to the budget named in the finding. |
group_enum_enrols_an_identity | error | A groups entry combines from_enum with enroll: [enterprise_reader] or enroll_during_run: [operator], or membership: exclusive. Each of those acts on a single group, and from_enum makes one group per enum member, so the enrolment would apply to one of them and the rest would stay empty. An enum with no members generates no group at all, so it would apply nowhere. Set enroll on a group declared on its own. An enum with exactly one member is not reported: there is one group and the identity lands in it. |
group_enum_name_not_unique | error | A groups entry declares from_enum but its name carries no {member} placeholder, so every member resolves to the same name and one group is created instead of one per member. Nothing fails at deploy time: the single group is written, read back byte-identical and reported clean, while every grant meant for a particular member lands on it. Put {member} in the name, or {member_safe} where a member carries a character SharePoint refuses in a group name: both satisfy this rule, and {member} alone would trade this finding for group_name_invalid. An enum with a single member is not reported, because one name cannot collapse onto another. |
group_enum_unknown | error | A groups entry's from_enum names an enum the DBML does not declare, so no group is generated from it. Check the spelling against the schema's Enum blocks, or write the groups out. |
group_name_invalid | error | A declared group's name carries a character SharePoint refuses in a group name. Measured on a live tenant on 2026-09-21, the refused set is `" / \ [ ] : |
hide_is_unnecessary | warning | hide_from_all_items is set on an entity whose All Items view is already within the join ceiling with nothing hidden. |
hide_of_cross_site_reference | error | hide_from_all_items names a cross-site reference, which expands to a Choice + URL pair and costs no join operation. |
hide_of_non_join_bearing_column | error | hide_from_all_items names a column that costs no join operation; only a join-bearing column may be hidden. |
hide_of_unrendered_column | error | hide_from_all_items names a column the generated All Items view does not render -- usually a typo. |
hide_without_all_items_view | error | hide_from_all_items names a column on an entity for which no All Items view is generated at all, so the key would silently do nothing. |
identity_declared_not_enrolled | warning | An identity under identities: is enrolled by no group, so a value supplied for it would be refused. Enrol it, or delete the declaration. |
identity_kind_unknown | error | An identity's kinds is empty or names something other than user, security_group or m365_group. |
identity_name_invalid | error | An identity name must match [a-z][a-z0-9_]{0,63}, so its env key DBMLSP_IDENTITY_<NAME> is the name upper-cased with no other change. |
identity_redeclares_builtin | error | identities: declares enterprise_reader, automation or operator. These are built in; enrol them without declaring them. |
identity_unknown | error | enroll or enroll_during_run names an identity that is neither built in nor declared under identities:. |
illegal_column_name_character | error | A column name contains a character SharePoint rejects. |
index_column_not_rendered | error | An indexes { } entry names a column the deploy never creates. |
index_column_type_unindexable | error | An indexes { } entry names a column of a type SharePoint cannot index. |
index_duplicates_unique_column | error | An indexes { } entry names a column that already carries an implicit index from its [unique] setting. |
index_limit_approaching | warning | A list has reached 18 of its 20 indexes. SharePoint creates indexes by itself -- opening a sorted view on an unindexed column adds one -- and those are invisible to this build, so leave headroom. |
index_limit_exceeded | error | A list's effective indexes exceed SharePoint's limit of 20. The message names the implicit contributors, which are the ones an author cannot count. |
index_on_calculated_column | error | An indexes { } entry names a calculated column. SharePoint accepts the flag and reads it back false. |
index_settings_unsupported | error | A DBML index carries name, unique, type, pk or note. SharePoint exposes none of them, so declare a bare column index. |
join_threshold_approached | warning | A view renders 11 or 12 join-bearing columns, the two counts before the measured ceiling of 12 join operations. 12 held on the tenant measured, but the SharePoint Online citation is thin, so a view this wide may not travel to every tenant. |
join_threshold_exceeded | error | A view renders more join-bearing columns than the measured ceiling of 12 join operations, and SharePoint returns the view blank at any list size. Reached from a declared view and from the generated All Items view. |
legacy_choice_type | error | A column uses the legacy choice type instead of a named DBML enum. |
library_group_by_folder_scoped | warning | A recursive library view groups by a column. Measured on a document library past the list view threshold (analysis/limits.py, library.large-list.preindex-group-by-refusal-signature and library.large-list.foldered-group-by-folder-scoped, 2026-09-08): a root-scoped group-by is refused at that size, an index does not lift the refusal, and the same grouping is served only inside a folder that is itself under the threshold. The view works until the library reaches that size, and then its grouping stops rendering at the root. |
library_name_display_column_unreadable | error | A document library that lookups point at declares display_column: FileLeafRef. Such a lookup is created bound to the file Name and its picker lists every file, and then a row holding a value answers HTTP 500 to the item read the deploy verifies every write with, a view renders the value as 2_.000 rather than the file name, and while the column exists the list's whole-item read fails with no value set (measured on a live tenant, 2026-09-18, four runs). A calculated copy of the name cannot stand in: =[Name] on a library is refused at creation. Bind the lookup to Title and give each file a Title, or link the file from a hyperlink column. |
library_setting_on_a_list | error | settings is declared on an entity that is not a DocumentLibrary. Its one key, require_checkout, writes the library's ForceCheckout property, which is the library's "Require Check Out" control (library.checkout.force-checkout-merge). Remove the key, or declare kind: DocumentLibrary with base_template: 101. |
list_validation_formula_too_long | error | A list_validation: rule renders to a formula longer than 1023 characters once display names are substituted. |
list_validation_message_too_long | error | A list_validation: message is longer than 1024 characters. |
list_validation_references_a_retired_column | error | A list validation condition references a column that has been retired. |
lookup_crosses_site_role | error | A lookup's source and target entities map to different site_roles; a SharePoint lookup cannot span webs. |
lookup_display_column_unknown | error | A lookup target declares a display_column that is not one of its columns, so the deploy would emit an unresolvable LookupField. |
lookup_would_render_blank | error | A lookup target has no Title column and declares no display_column, so every lookup into it renders blank. |
marker_family_missing | error | The schema declares no Project name, so there is nothing to attribute the objects this build provisions to. The marker is how a later deploy tells its own objects from somebody else's, and how rollback decides what it may delete. Declare Project my_thing { } in the DBML. |
marker_family_not_canonical | error | The DBML Project name can collide with another family's ownership marker after normalization. Use underscores instead of hyphens or slashes, remove surrounding whitespace, and avoid family text that looks like for list, for group, or for level. Existing hyphen or slash names can usually move to the underscore spelling without changing the emitted marker. |
marker_field_has_reserved_text | error | A name the provenance marker interpolates contains text the marker reserves: either ., which terminates it, or Provisioned by dbml-sharepoint, which opens it. Both are what keep one marker from sitting inside another. A name holding . makes from risk. a substring of from risk.v2.; a name holding the opening text makes the marker carry another family's complete marker as a suffix. Either way a different family's adoption gate matches this object and takes whatever access that family declares. Rename the family, entity, group or permission level without the reserved text the finding names. |
marker_longer_than_the_field | error | The provenance marker alone is longer than the Description field it has to fit in, before any declared text is added. The budget check clamps to zero and an empty description then passes it, so without this the deploy would emit the overlong marker and SharePoint would refuse it part-way through provisioning. Shorten the Project name, or the group or level name. |
minor_versions_without_versioning | error | An entity's versioning settings resolve to enable_minor_versions: true with enable_versioning: false. Measured on a live site 2026-09-06 (field.list.minor-versions-sticks): a generic list refuses that write with HTTP 500, -2146232832, Microsoft.SharePoint.SPException, "The list does not support minor versioning", and the flag reads back false. The deploy sends both flags in one body, so the paste stops at that list. Set enable_versioning: true, or drop enable_minor_versions. The settings are read as the per-entity versioning.overrides block merged onto versioning.default, so either can be the one to fix. A document library accepted the same pair in that run (HTTP 204, read back true), which is why the rule reads the entity's kind; libraries are refused for unrelated reasons. |
multi_value_condition_operator_unsupported | error | A condition asks a multi-value column something with no verified rendering. Measured on 2026-08-10 for Choice and on 2026-09-04 for Lookup: CAML's <Eq> against such a column tests MEMBERSHIP rather than equality, so membership is spelled includes and eq is refused rather than quietly meaning two different things on two columns. includes, not_includes, is_null and is_not_null are the four measured, on both kinds; contains works on a Choice but cannot be told apart from a substring match. <Includes>/<NotIncludes>, the two operators Microsoft documents, returned nothing at all on a Choice; on a Lookup they work and return what <Eq>/<Neq> return, so one rendering serves both. |
multi_value_default_unsupported | error | A multi-value column declares default:. DBML carries one scalar and SharePoint's write shape for the column is a collection, so there is no coercion that says what was declared. Refused rather than dropped: a dropped default is invisible in a green build. |
multi_value_filtered_view_unindexable | warning | A view filters on a multi-value column and nothing else in the filter carries an index. The usual remedy does not apply: SharePoint refuses an index on such a column, so following it would fail the build. Filter on a scalar column instead. |
multi_value_index_unsupported | error | An indexes { } entry names a multi-value column. Measured on 2026-08-10 for a Choice (multi-valued) column and on 2026-09-02 for a Lookup (multi-valued) one: SharePoint refuses the index and reads Indexed back as false, against single-value controls in the same list that stuck. The lookup refusal is HTTP 500, "This column type is not supported for indexing". The same column without the brackets is indexable. A multi-value lookup can never be indexed by any route: indexing the source list's column does not carry into it either, measured on 2026-09-04 with the lookup created before the source index and again with it created after. |
multi_value_member_contains_the_export_separator | error | An enum member used by a multi-value column contains ; , the separator the exported cell joins members with. A set holding that member exports to the same text as a set holding its parts, so the cell cannot be split back into what the row actually held and any count of selections taken from it is wrong with nothing able to notice. The deploy is unaffected -- the list, the column and the form all work -- but every build emits the reporting bundle, so the ambiguous export is always produced. Rename the member, or model the column as a child entity with one row per value. Only ; is refused; a bare ; joins and splits back perfectly well. |
multi_value_membership_on_a_single_value_column | error | includes or not_includes is used on a column that holds exactly one value. Both render <Eq>/<Neq>, which on a single-value column means equality -- so accepting them would give the word two meanings from the other side. Use eq/neq, or declare the column as an array of its enum if it really does hold many. |
multi_value_operand_unsupported | error | A calculated formula, a validation formula or a conditional show/hide rule reads a multi-value column. Measured on 2026-08-10: a calculated field refused it with HTTP 500 and a validation formula with "This field type does not support validation formulas"; show/hide is documented unsupported and would save and silently never react. A VIEW filter over the same column works. |
multi_value_set_equality_unsupported | error | A membership test's value contains ;#, the separator SharePoint puts between the members of a set. Measured on 2026-08-10: <Eq> against such a value stops testing membership and matches the whole set instead -- one operator, two questions, told apart only by the value. Name a single member. Exact-set equality is not offered because it is not characterised: the probe sent the members in one order and never in the other, so whether SharePoint compares the delimited string literally or normalises the set first is unknown. |
multi_value_style_renders_a_false_neutral | error | A severity or pill style sits on a multi-value column. Both compare @currentField against quoted strings and a multi-value field is an array, so no branch matches and every cell takes the fallback. Watched on a live site on 2026-08-10: that is a filled grey cell on every row -- a verdict rather than a gap, and invisible to the build and the deploy alike. |
multi_value_unique_unsupported | error | [unique] is declared on a multi-value column. SharePoint cannot enforce unique values on a Choice (multi-valued) column, and measured on 2026-08-10 refuses EnforceUniqueValues on one with HTTP 500. |
multiple_default_views | error | More than one view on an entity is marked default; a SharePoint list has exactly one. |
multiple_enterprise_reader_groups | error | More than one group is marked enroll: [enterprise_reader]. build --enterprise-reader takes one address and needs one unambiguous target. |
operator_enrolled_persistently | error | enroll: names operator, or enroll_during_run: names a persistent identity. The operator is added and removed within one run and goes in enroll_during_run; every other identity stays and goes in enroll. |
orphan_enum | warning | An enum is defined but no column references it. |
overdue_guard_field_not_rendered | error | An overdue-date style's guard.field names a column the entity does not render. |
permission_level_description_too_long | error | A permission_levels: entry's description is longer than 512 characters. MEASURED 2026-08-14 against a live tenant: SharePoint answers a longer one with HTTP 500 and the message "The parameter Description cannot be bigger than 512 characters." It REFUSES rather than truncating, and it does so in deploy phase 1.3 -- part-way through writing permission levels and before any list exists -- so the run stops against a half-provisioned site. Shorten the description. SP.RoleDefinition.Description is a different surface from a group's description and was measured separately, even though the two ceilings agree today. |
permission_level_description_too_long_for_marker | error | A permission_levels: entry's description leaves no room for the provenance marker appended to it. The deploy stamps every level it writes with Provisioned by dbml-sharepoint, and the adoption gate refuses to adopt a level whose description does not carry it, so a truncated marker would make the tool refuse a level it created itself. Shorten the description to the budget named in the finding. |
permission_level_not_directly_assignable | error | A list_permissions assignment names Limited Access or Web-Only Limited Access. Microsoft Learn is explicit that SharePoint assigns these itself and that they cannot be assigned directly: they are what a principal ends up holding on a parent web or list so it can reach one item granted below it, and they grant no additional access on their own. Writing one into a mapping is not a narrow grant -- it is a request the site does not honour as written, leaving the effective access decided by SharePoint's inheritance rather than by anything a reader of the mapping can see. Grant the level you actually mean, usually Read, and let SharePoint derive the rest. |
permission_level_redefines_a_builtin | error | A permission_levels: entry is named after a built-in SharePoint permission level. SharePoint itself permits a duplicate name -- built-in-levels-probe.js renamed a custom level to Read on a live site on 2026-09-06 and the site accepted it, with getbyname still resolving to the built-in -- but the deploy does not create a second level beside it: it probes for a role definition of that name and, finding the site's own, MERGEs the declared description and base permissions onto it. That reconciliation is deliberate -- it stops a drifted custom level silently keeping edit rights -- but pointed at a built-in it rewrites Read (or whichever) for EVERY principal on the site that holds it, not just the ones this mapping names. Give the custom level a name of its own. Matched case-insensitively, the same way duplicate level names are, because the site resolves the name to one object either way. The eleven reserved names come from Microsoft Learn, 'Permission levels in SharePoint'; they are ENGLISH, and built-in levels are locale-dependent, so this cannot catch the collision on a non-English tenant. |
polymorphic_column_not_rendered | error | A polymorphic_patterns: entry's field or discriminator names a column the deploy never creates. |
previous_title_claimed_twice | error | Two views claim the same previous title. |
previous_title_is_a_current_title | error | A renamed_from entry is another declared view's current title. |
previous_title_is_own_title | error | A renamed_from entry repeats the view's own current title. |
previous_title_is_reserved | error | A renamed_from entry claims All Items, which is reserved for the generated recovery view. |
projection_column_has_no_ref | error | A lookup_projections: entry names a column with no DBML ref:. |
projection_name_collides | error | A lookup projection's generated dependent field has the same name as a column the DBML already declares. |
projection_name_too_long | error | A lookup projection's generated dependent field exceeds SharePoint's 32-character internal-name limit. |
projection_on_cross_site_ref | error | A lookup_projections: entry names a cross-site reference column, which expands to Choice and URL fields rather than a primary lookup, so it cannot carry a dependent projection. |
projection_target_kind_unsupported | error | A lookup_projections: entry projects a column whose field kind the reporting pack cannot carry. A projection is read through the lookup's $expand, and a person, a URL, a multi-value column or another lookup arrives there as a record or a collection whose shape has not been measured. The deploy would create the dependent field; the report could not type it. Project a scalar column, or carry this one by joining the target table in the model. |
projection_unknown_column | error | A lookup_projections: entry names a column the entity's table does not declare. |
projection_unknown_target_column | error | A lookup_projections: entry projects a column the lookup target does not declare. |
redundant_display_column_acceptance | warning | accept_unindexable_display_column is set on an entity with nothing to accept: nothing looks it up, or its display column is not calculated. |
release_deployer_version_ignored | warning | release.yaml sets deployer_version, which the build no longer reads. The deployer that script headers, the deploy manifest and every Deployments row record is the installed package's own name and version, read from its metadata at build time. The key was written by hand and had drifted: most shipped files said 0.1.0 whatever version built them. The file still loads. Remove the key to clear this warning. |
renamed_from_claimed_twice | error | renamed_from resolves to one previous name on more than one entity, group or permission level, or twice on one, so two would race to adopt the same existing object. |
renamed_from_is_a_declared_entity | error | renamed_from resolves to a previous name that is still a declared entity, group or permission level, so a redeploy would find both and could not tell a rename from a collision. |
required_column_hidden_from_the_new_form | error | A required column with no default is hidden from the New form, so every save would fail. Statically provable, hence an error. |
required_column_may_be_hidden_at_creation | warning | A required column with no default has a when that MAY hide it at creation. Whether it does depends on what the person types, so the build cannot decide it -- a warning by design, per the form_visibility spec. |
reserved_column_name | error | A column uses a name SharePoint reserves. |
retired_column_in_field_set | warning | A field set names a retired column; retirement strips it from every view that expands the set, and the build continues. |
retired_column_not_rendered | error | A retired_columns entry names a column the DBML does not declare. Retire the declared column rather than deleting the declaration. |
retired_column_required_with_a_default | warning | A retired column is required and has a declared default, so every new row is still stamped with that value. |
retired_column_still_indexed | warning | A retired column is still named in the DBML indexes block, spending part of a finite index budget. |
retired_date_not_iso | error | A retired: date is not an ISO YYYY-MM-DD date. |
retirement_stripped_a_declaration | warning | The load-time retirement fold removed a retired column from a declaration that still names it; the build continues. |
retirement_without_display_names | warning | Columns are retired but display_names is not enabled, so the ' (retired)' title suffix never reaches SharePoint. |
row_limit_out_of_range | error | A view's row_limit is outside 1-5000. |
sharepoint_group_enrolled | error | A group's enroll or enroll_during_run names a SharePoint group. Microsoft Learn says SharePoint groups cannot be nested (the page is written for SharePoint Server, so this refuses on its word). To give a site's own Owners, Members or Visitors a defined group's access, grant the same level to associated_owner_group, associated_member_group or associated_visitor_group. |
style_calculated_type_mismatch | error | calculated: true is set on a style whose column is not the calculated_* type that style expects. |
style_input_type_mismatch | error | A numeric or date style has an incompatible target or comparison operand. Use a scalar of the required type. Microsoft documents lookup fields as objects with lookupId and lookupValue, not scalar integers (formatting reference). For a lookup, use custom formatting that selects the intended property. |
style_map_key_not_in_enum | error | A severity or pill map names a choice the column's enum does not contain. |
style_on_boolean_matches_nothing | error | A severity or pill style sits on a Yes/No column. Both compare @currentField against quoted strings, so every branch is false and the cell renders unstyled -- silently. |
style_requires_calculated | error | A style target or comparison operand uses the matching calculated_* column but does not set calculated: true, so SharePoint's typed formatter value is never decoded. |
superseded_by_is_itself_retired | error | A superseded_by names a column that is itself retired. |
superseded_by_names_the_retired_column | error | A superseded_by names the retired column itself. |
superseded_by_not_rendered | error | A superseded_by names a column the list does not render. |
total_column_not_displayed | error | A totals entry names a column that is not one of the view's fields, so SharePoint has no column to put the figure under. |
total_needs_numeric_column | error | A numeric-only total is declared on a non-numeric column. |
total_on_lookup_column | error | A total other than count is declared on a lookup column, whose stored value is a row id rather than a quantity. |
total_on_non_arithmetic_column | error | A total other than count is declared on a person, rich-text, long-text or hyperlink column. |
trend_against_not_rendered | error | A trend style's against names a column the entity does not render. |
undeployable_column_declaration | error | A per-column declaration targets Title or a SharePoint system column. The deploy never writes those properties, so the declaration would validate clean and do nothing. |
undeployable_declaration_column | error | A per-column declaration sits on Title or a SharePoint system column, which the deploy never writes these properties to. It would validate clean and deploy nothing. |
unindexed_filter_columns | warning | A view's where filters on columns with no effective index, so past the list view threshold SharePoint may silently return a truncated answer. |
unique_unsupported_for_type | error | [unique] is declared on a type SharePoint cannot enforce it for. |
unique_without_not_null | warning | [unique] without not null, so uniqueness is enforced only on populated values. MEASURED 2026-09-13 (field.unique.blank-values-coexist, field.unique.empty-string-values-coexist in unique-blanks-probe.js): two items that omit the column both land, and so do two that send it as an empty string, while a second item repeating a populated value is refused. |
unknown_base_permission | error | A permission_levels entry names a base permission bit SharePoint does not have. |
unknown_column_type | error | A column's DBML type is not one the typemap knows. |
unknown_entity | error | A mapping section names an entity the mapping does not declare. |
unknown_field_set_reference | error | A view's fields references @name, but the entity declares no field set of that name. |
unknown_owner_group | error | A group's owner_group is neither a built-in SharePoint group nor a declared custom one. |
unknown_permission_level | error | An assignment names a permission level that is neither built- in nor declared. |
unknown_principal_group | error | An assignment names a group that is neither built-in nor declared. |
unknown_ref_target | error | A ref points at a table the schema does not define. |
unknown_retention_policy | error | A retention list_defaults entry names a policy that is not defined. |
unknown_site_role | error | list_permissions.default.site_role names a role no entity declares. |
unknown_table | error | A list_permissions.overrides key is not a DBML table name. Use the unprefixed name. |
unmapped_schema_table | error | A DBML table has no entities: entry, so it would be dropped from the deploy plan without an error. |
unresolvable_associated_group_alias | error | An assignment names a built-in associated-group alias that cannot be resolved by name at deploy time; real sites name it ' |
unsupported_base_template | error | An entity's base_template is neither 100 (a generic list) nor 101 (a document library). The create call sends BaseTemplate and never sends kind, so any other number provisions a container the rest of the build does not model. |
validation_formula_too_long | error | A rendered validation formula exceeds SharePoint's 1023-character limit. |
validation_message_too_long | error | A column validation message exceeds 1024 characters. |
view_emptied_by_retirement | warning | Retirement stripped every declared field from a view, which would be created with no columns. |
view_filter_exceeds_editor_capacity | warning | A view's where renders more than 10 comparisons, which is more than the classic filter editor can show. The emitted filter is protected, so this is survivable; if that protection is ever removed or fails to take, the view loses the comparisons past the ceiling the first time somebody opens its settings. A negated clause renders two comparisons, not one. |
view_formatter_xml_metacharacter | error | A view formatter contains a raw & or <. A view's CustomFormatter is stored in the view schema XML, so those reach SharePoint as markup and the document it assembles is malformed -- the view MERGE returns HTTP 500 with a System.Xml.XmlException and the deployment aborts part-way. Nothing before that point can see it: the build is clean and so is node --check. Measured on a live tenant 2026-08-11 by test/manual/formatter-xml-probe.js: & and < are refused, while >, >=, " and ' are all accepted (> comes back as >). So the remedy for < is to flip the comparison -- 0 > Number([$Km]) rather than Number([$Km]) < 0, which is the same predicate and the same behaviour on a blank -- and the remedy for && is to nest an if(). ` |
view_scope_on_a_list | error | A view declares scope on an entity that is not a DocumentLibrary. Scope decides whether a view shows the files in every folder or only the folder being viewed, and a list has no folders for it to flatten. |
watch_use_id_duplicate | error | More than one use on the same entity's watched columns shares an id, which must name one use so a consumer can tell them apart. |
watch_use_id_invalid | error | A watched column's use id is not lowercase letters, digits and hyphens starting with a letter. An id names what the consumer builds, so it takes a use name's spelling. |
watch_use_name_invalid | error | A watched column's use name is not lowercase letters, digits and hyphens starting with a letter. |
watch_use_repeated_without_id | error | A use name appears more than once on one entity's watched columns and this occurrence has no id to tell it from the others. |
watch_use_when_required | error | A use with on: enter or on: leave has no when, so there is no condition for the column's value to enter or leave. |
watched_column_not_rendered | error | A watched_lists: entry names a column the deploy never creates. |
width_column_not_displayed | error | A widths entry names a column that is not one of the view's fields. |
width_out_of_range | error | A column width is outside 16-2000 pixels. |