tinyhumansai/openhuman · error

turn model source is missing a model

Error message

turn model source is missing a model

What it means

TurnModelSource::build fell through both branches: neither direct_model nor crate_native is set (mod.rs:1608, struct at 1389). TurnModelSource is a two-case sum emulated with Options; every constructor sets exactly one, so this error means the source was constructed empty — an internal wiring bug (a Default or struct literal with both fields None), not a user configuration problem.

Source

Thrown at src/openhuman/agent/tinyagents/mod.rs:1608

                    .split(':')
                    .next()
                    .unwrap_or(&provider_string)
                    .to_string()
            };
            return build_turn_models_crate(
                &cn.role,
                &cn.config,
                model,
                temperature,
                context_window,
                cn.primary_override.as_deref(),
                provider_id,
                !is_local,
                !is_local,
                cn.force_text_mode,
            );
        }
        Err(anyhow::anyhow!("turn model source is missing a model"))
    }

    /// Build a standalone summarizer [`ChatModel`](tinyagents::harness::model::ChatModel)
    /// over this source's provider — a fresh adapter (own error slot) for one-off
    /// summary calls outside the main turn (e.g. the sub-agent cap-hit checkpoint),
    /// so the caller can `invoke` without naming the `Provider` trait. The output
    /// cap rides the per-call `ModelRequest`, not the model.
    pub(crate) fn build_summarizer(
        &self,
        model: &str,
        temperature: f64,
    ) -> anyhow::Result<Arc<dyn tinyagents::harness::model::ChatModel<()>>> {
        if let Some(direct) = &self.direct_model {
            let profile = direct.profile().cloned().unwrap_or_default();
            return Ok(Arc::new(
                ProfileOverrideModel::new(direct.clone(), profile)
                    .with_request_model(model)
                    .with_request_temperature(temperature),

View on GitHub (pinned to a221052e0d)

Solutions

  1. Construct the source with a real constructor (direct-model injection or the new_crate_native* family) so exactly one branch is Some
  2. If you added a new source kind, extend build() with its branch before the final Err
  3. Add a constructor-level guard (debug_assert or explicit error) that at least one Option is set

Example fix

// before
let source = TurnModelSource { direct_model: None, crate_native: None, force_text_mode: false };

// after
let source = TurnModelSource::new_crate_native_from_string(role, provider_string, config);
Defensive patterns

Strategy: validation

Validate before calling

// Internal: assert the source is configured before building turn models
fn assert_configured(source: &TurnModelSource) -> anyhow::Result<()> {
    if source.direct_model.is_none() && source.crate_native.is_none() {
        anyhow::bail!("TurnModelSource built without a model source — use a real constructor");
    }
    Ok(())
}

Type guard

// Internal narrow: exactly-one-Option invariant of the two-case sum
impl TurnModelSource {
    fn configured(&self) -> bool {
        self.direct_model.is_some() ^ self.crate_native.is_some()
    }
}

Try / catch

// Add context so the invariant break is diagnosable at the call site
source.build(model, temp, ctx).await
    .context("assembling turn harness: TurnModelSource had neither direct nor crate-native model")?

Prevention

When it happens

Trigger: A new call site building TurnModelSource via struct literal or Default instead of the provided constructors; a refactor adding a third source kind without extending build(); test scaffolding meaning to inject a direct model but passing None.

Common situations: Feature work on the agent harness adding model-source paths; CI failures in newly added turn-assembly tests; code copied from a constructor that then gets its body stripped.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/42d9eff5b6007424. Report an issue: GitHub.