How to Debug Configuration Issues and Parameter Resolution Problems in Hypster

Hypster resolves configuration values through a two-stage pipeline where instantiate creates an HP instance and executes your config function, comparing user-supplied keys against called_params to detect unknown or unreachable parameters with typo suggestions.

Hypster is a Python library for managing complex configuration objects through code-first configuration functions. When parameter resolution fails or unexpected keys appear, understanding the internal instantiation pipeline—from signature validation in src/hypster/utils.py to parameter tracking in src/hypster/hp.py—is essential for effective debugging.

Understanding Hypster's Two-Stage Configuration Pipeline

Hypster builds configuration objects through a strict two-stage process implemented in src/hypster/core.py. First, the instantiate function (lines 17-66) creates an HP instance from your values mapping and executes your configuration function. Second, calls to hp.int(), hp.select(), or hp.nest() inside that function retrieve, validate, and record parameter values in the called_params set.

The library maintains a shared registry of accessed parameters across nested configuration blocks. When execution completes, _handle_unknown_parameters (lines 73-106 in src/hypster/core.py) compares the keys you supplied against the called_params set populated during execution. Mismatches trigger warnings or errors depending on your on_unknown setting, with suggestions generated by suggest_similar_names in src/hypster/utils.py using difflib.SequenceMatcher.

Common Configuration Errors and Their Root Causes

Configuration failures typically originate from three layers: signature validation, parameter name collisions, or value validation.

Symptom Root Cause Source Location
ValueError: Configuration function foo must have 'hp: HP' as first parameter Config function lacks hp: HP as first parameter validate_config_func_signature in src/hypster/utils.py
UserWarning: Unknown or unreachable parameters with typo suggestions Supplied key doesn't match any called parameter; library suggests alternatives _handle_unknown_parameters in src/hypster/core.py and suggest_similar_names in src/hypster/utils.py
HPCallError: param_name has already been defined Duplicate parameter access, often via nesting _validate_name_not_called in src/hypster/hp.py
HPCallError: prefix 'model' reserved Nesting prefix collides with existing parameter name nest method in src/hypster/hp.py
Type errors or out-of-bounds values Validators reject supplied values _handle_single_value / _handle_multi_value in src/hypster/hp.py

Step-by-Step Debugging Workflow

Validate the Configuration Function Signature

Before parameter resolution begins, Hypster validates that your function accepts hp: HP as its first argument. If the signature is invalid, instantiate raises immediately.

from hypster import instantiate

def my_config(hp):  # Must declare hp: HP as first parameter

    return hp.int(10, name="batch_size")

# This validates the signature and raises ValueError if incorrect

instantiate(my_config, values={})

Inspect the Raw Values Dictionary

Hypster accepts both dotted keys ("model.hidden_units": 128) and nested dictionaries ({"model": {"hidden_units": 128}}). The utility unflatten_dict in src/hypster/utils.py converts dotted notation to nested structures for lookup. Verify your keys match the expected structure before debugging deeper.

Check Which Parameters Were Actually Accessed

After execution, inspect hp.called_params to see exactly which parameters your function resolved. This set is updated by every public HP method including int, select, and nest.

def inspect_cfg(hp):
    hp.int(10, name="batch_size")
    hp.float(0.001, name="learning_rate")

# Capture the HP instance to inspect internal state

result = instantiate(inspect_cfg, values={"batch_size": 32, "learning_rate": 0.01}, on_unknown="ignore")
print(result.called_params)  # Output: {'batch_size', 'learning_rate'}

Identify Unknown Parameters with Strict Validation

By default, Hypster warns about unknown parameters. Force hard failures during debugging by setting on_unknown="raise". The error message includes similarity scores from difflib.SequenceMatcher to catch typos.

def cfg(hp):
    lr = hp.float(0.01, name="learning_rate")

values = {"lr": 0.005}  # Typo: should be "learning_rate"

try:
    instantiate(cfg, values=values, on_unknown="raise")
except ValueError as e:
    print(e)  # Shows: "Unknown or unreachable parameters: - 'lr': Did you mean 'learning_rate'? (similarity: 73%)"

Debug Nesting and Namespace Collisions

Each hp.nest(child, name="sub") creates a new HP instance with its own namespace_stack while sharing the parent's called_params. Duplicate names across nesting boundaries raise HPCallError. Verify that nesting prefixes don't clash with existing parameter names, as enforced by the nest method in src/hypster/hp.py.

def child_cfg(hp):
    hp.int(128, name="hidden_units")

def parent_cfg(hp):
    hp.int(64, name="hidden_units")  # Error if not namespaced

    hp.nest(child_cfg, name="model")  # Creates namespace 'model'

Enable Verbose Warnings

Ensure all UserWarning messages from _handle_unknown_parameters are visible by configuring the warnings filter at the start of your debugging session:

import warnings
warnings.filterwarnings("always", category=UserWarning)

Practical Code Examples

Debugging Typos with Explicit Error Handling

from hypster import instantiate

def training_config(hp):
    hp.int(32, name="batch_size")
    hp.float(0.001, name="learning_rate")
    hp.select(["adam", "sgd"], name="optimizer")

# Intentionally misspelled key to trigger suggestion logic

values = {"batch_size": 64, "learning_rate": 0.01, "optimzer": "adam"}

instantiate(training_config, values=values, on_unknown="raise")

Inspecting Consumed vs. Supplied Parameters

def model_cfg(hp):
    hp.int(128, name="hidden_units")
    hp.float(0.5, name="dropout")

values = {
    "hidden_units": 256,
    "dropout": 0.2,
    "unused_param": 999  # This will be flagged

}

# Use ignore to prevent exceptions, then check the returned object

config = instantiate(model_cfg, values=values, on_unknown="ignore")
print(f"Accessed: {config.called_params}")
print(f"Expected: {set(values.keys())}")

Handling Duplicate Parameter Definitions

def duplicate_cfg(hp):
    hp.int(1, name="seed")
    # This will raise HPCallError in _validate_name_not_called

    hp.int(42, name="seed")

try:
    instantiate(duplicate_cfg, values={})
except ValueError as e:
    print(f"Configuration error: {e}")  # "seed has already been defined"

Summary

  • Hypster's pipeline consists of instantiate creating an HP instance, executing your config function, and comparing supplied keys against called_params via _handle_unknown_parameters.
  • Unknown parameters trigger warnings by default; use on_unknown="raise" for CI-friendly strict validation with typo suggestions powered by difflib.SequenceMatcher in src/hypster/utils.py.
  • Signature validation occurs in validate_config_func_signature in src/hypster/utils.py and requires hp: HP as the first parameter.
  • Duplicate parameters across nesting boundaries raise HPCallError from src/hypster/hp.py; each nest() call maintains a namespace_stack while sharing the parent's parameter registry.
  • Debugging tools include inspecting called_params, enabling warnings.filterwarnings("always"), and using dotted or nested dictionary syntax interchangeably via unflatten_dict.

Frequently Asked Questions

Why does Hypster report my parameter as "unknown or unreachable"?

This occurs when a key in your values dictionary does not match any parameter accessed during configuration function execution. The HP class tracks accessed parameters in called_params, and _handle_unknown_parameters in src/hypster/core.py compares this set against your inputs. If a key is present in values but never retrieved via hp.int(), hp.float(), or similar methods, Hypster flags it as potentially obsolete or misspelled, offering suggestions via suggest_similar_names.

How can I see exactly which parameters my config function consumed?

After calling instantiate, access the called_params attribute on the returned configuration object. This set contains the fully-qualified names of all parameters resolved during execution, updated by every HP method in src/hypster/hp.py. Compare this against your input values keys to identify unused or misspelled parameters during debugging.

What causes the "parameter has already been defined" error?

The HPCallError originates in _validate_name_not_called within src/hypster/hp.py when your configuration function attempts to define the same parameter name twice. This commonly happens when nesting configurations that inadvertently share parameter names without proper namespacing, or when manually calling hp.int() or similar methods with duplicate name arguments in the same scope.

How do I enable strict validation to catch typos in parameter names?

Pass on_unknown="raise" to the instantiate function in src/hypster/core.py. This forces Hypster to raise a ValueError instead of emitting a UserWarning when encountering keys in your values dictionary that don't match any called parameters. The error message includes similarity scores calculated by difflib.SequenceMatcher in src/hypster/utils.py, making it ideal for catching typos in CI pipelines.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →