Skip to content

openmc.Settings Allows Arbitrary Attribute Assignment, Leading to Silent User Errors #3741

@Submerging

Description

@Submerging

Description

-- The openmc.Settings class currently allows arbitrary dynamic attribute assignment, e.g.:

settings = openmc.Settings()
settings.sources = definedsource     # typo: should be "settings.source"
settings.particle = 1000      # typo: should be "settings.particles"
settings.xxxxx = source       # completely unknown attribute

Impact

1. Silent failures

A simple typo, such as: settings.particle = 1000, does not raise an exception. The user believes the setting is applied, but OpenMC actually uses the default particles value.

2. Simulations complete successfully

Because OpenMC ignores unknown attributes, the simulation runs normally, producing output files without any indication of misconfiguration.

3. Results may be severely wrong

Incorrect settings (e.g., wrong particle count, wrong run mode, wrong cutoff parameters) can lead to:
-- incorrect eigenvalue estimates

-- incorrect tally statistics

-- incorrect variance reduction behavior

-- incorrect source distribution

These errors propagate silently.

4. Debugging is extremely difficult

Users may spend hours or days trying to understand why results are inconsistent, without realizing the root cause is a simple typo that OpenMC silently ignored.

Alternatives

  • Expected Behavior
    OpenMC should reject unknown attributes assigned to Settings objects, raising an explicit error so users can immediately detect configuration mistakes.
  • Proposed Solution
    Introduce a restrictive setattr implementation in Settings that:

Allows internal _xxx attributes during initialization

Allows assignment to existing attributes (including properties)

Allows internal _xxx attributes after initialization

Rejects all unknown attributes with a clear error message

  • Suggested Implementation in openmc.settings
def __setattr__(self, name, value):
    # 1. During initialization: allow all _xxx attributes
    if getattr(self, '_initializing', False):
        super().__setattr__(name, value)
        return

    # 2. Allow existing attributes (including properties)
    if hasattr(self, name):
        super().__setattr__(name, value)
        return

    # 3. Allow internal attributes (_xxx)
    if name.startswith('_'):
        super().__setattr__(name, value)
        return

    # 4. Otherwise → forbid
    raise AttributeError(f"Unknown Settings attribute '{name}'")

Compatibility

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions