openmediavault/openmediavault · error · SchemaException

No 'properties' attribute defined at

Error message

No 'properties' attribute defined at '%s'.

What it means

Datamodel._walk_schema requires every node with type 'object' to define a 'properties' attribute, because it iterates schema['properties'] to recurse into child nodes. An object node without 'properties' is treated as an untraversable malformed schema and raises json.SchemaException with the failing path. Like error 150 this is a schema-definition bug, not bad data.

Solutions

  1. Locate the path from the message in the datamodel schema and add a 'properties' object listing the child fields (use "properties": {} only if intentionally empty and the walker should not recurse).
  2. Run the schema through openmediavault.json.Schema validation in a unit test to catch structural gaps before shipping.
  3. Rebuild/re-register the plugin schema (dpkg install or omv-mkconf) so the fixed schema is loaded.
  4. Diff the schema against a known-good upstream version to see what got lost.

Example fix

// before
"notification": { "type": "object" }
// after
"notification": { "type": "object", "properties": { "enabled": { "type": "boolean" } } }
Defensive patterns

Strategy: validation

Validate before calling

def validate_object_schemas(schema):
    for key, node in schema.items():
        if isinstance(node, dict):
            if node.get("type") == "object" and "properties" not in node:
                raise ValueError(f"Object '{key}' missing 'properties'")
            validate_object_schemas(node)

Type guard

def has_properties(node: dict) -> bool:
    return isinstance(node, dict) and node.get("type") == "object" and "properties" in node

Try / catch

try:
    datamodel.walk_schema(path, callback)
except openmediavault.json.SchemaException as e:
    logging.error("Malformed datamodel schema: %s", e)

Prevention

When it happens

Trigger: Datamodel.walk_schema() (called by DatabaseQuery walks and ConfigObject) reaches a schema node {"type": "object"} with no 'properties' key — typically an empty or truncated object definition in the datamodel schema.

Common situations: Plugin authors declaring a nested object but forgetting its properties block; schema generated/merged by tooling that strips empty 'properties'; hand-editing config.xml.rng-derived schemas and dropping the properties map.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of openmediavault/openmediavault@dce610eb66 (2026-09-15). Data as JSON: /api/errors/8bc13d0699cad671. Report an issue: GitHub.

Appendix: source

Thrown at deb/openmediavault/usr/lib/python3/dist-packages/openmediavault/config/datamodel.py:335

            if not "type" in schema:
                raise openmediavault.json.SchemaException(
                    "No 'type' attribute defined at '%s'." % path
                )
            if "array" == schema['type']:
                # Validate the node.
                if not "items" in schema:
                    raise openmediavault.json.SchemaException(
                        "No 'items' attribute defined at '%s'." % path
                    )
                # Call the callback function.
                if callback(self, name, path, schema, user_data) is False:
                    return
                # Process the array items.
                _walk_schema(name, path, schema['items'], callback, user_data)
            elif "object" == schema['type']:
                # Validate the node.
                if not "properties" in schema:
                    raise openmediavault.json.SchemaException(
                        "No 'properties' attribute defined at '%s'." % path
                    )
                # Call the callback function.
                if callback(self, name, path, schema, user_data) is False:
                    return
                # Process the object properties.
                for prop_name, prop_schema in schema['properties'].items():
                    # Build the property path. Take care that a valid path
                    # is generated. To ensure this, empty parts are removed.
                    prop_path = ".".join([x for x in [path, prop_name] if x])
                    # Process the property node.
                    _walk_schema(
                        prop_name, prop_path, prop_schema, callback, user_data
                    )
            else:
                callback(self, name, path, schema, user_data)

        _walk_schema(

View on GitHub (pinned to dce610eb66)