tinyhumansai/openhuman · error · Error
settings.ai.slugMissingError|settings.ai.slugInUseError|sett
Error message
settings.ai.slugMissingError|settings.ai.slugInUseError|settings.ai.slugReservedError
What it means
submitProvider throws a precomputed slugError before ever calling onSubmit. slugError is derived in three ordered steps (AIPanel.tsx:3880-3886): slug empty (label slugifies to nothing) -> settings.ai.slugMissingError; slug already present in existingSlugs -> settings.ai.slugInUseError; adding (not editing, !initial) a slug in BUILTIN_RESERVED_SLUGS -> settings.ai.slugReservedError. The same slugError is rendered inline under the field and disables the Save button, so this throw only fires on programmatic submits or racing state.
Source
Thrown at app/src/components/settings/panels/AIPanel.tsx:3906
// Skipping verification is a bet that the provider works despite an
// unreadable listing. For an Azure host that is not the `/openai/v1` base
// that bet is already lost: `{base}/chat/completions` is not a route Azure
// serves there and the stored bearer auth is the wrong header, so the entry
// would be dead on arrival. Withhold the bypass and let the inline nudge do
// its job instead of manufacturing a broken provider (#5213).
const knownUnusableEndpoint =
isAzureFoundryEndpoint(endpoint) && !isAzureV1BaseUrl(endpoint.trim());
const submitProvider = async (opts?: { skipProbe?: boolean }) => {
setSaving(true);
setSubmitError(null);
// Cleared alongside the error: a later attempt that fails for an unrelated
// reason (slug collision, key write) must not still offer to skip
// verification, which is the distinction `ProviderProbeError` exists for.
setProbeFailed(false);
try {
if (slugError) {
throw new Error(slugError);
}
await onSubmit(
{
id: initial?.id ?? '',
slug,
label: label.trim() || slug,
endpoint: endpoint.trim(),
authStyle: initial?.authStyle ?? 'bearer',
maskedKey: maskKeyLabel(hasExistingKey || apiKey.length > 0),
},
apiKey.trim(),
opts
);
} catch (err) {
// Surface the failure inline and keep the dialog open so the user can fix
// the key/URL and retry. A rejected `/models` probe additionally unlocks
// the "add without verifying" button — the listing is a convenience for
// the model dropdown, not a precondition for inference.View on GitHub (pinned to 7491200858)
Solutions
- Change the label so its slug differs - add a distinguishing word or number
- To configure a built-in provider, edit the built-in entry instead of creating a custom one with its slug
- When editing an existing entry, the reserved check no longer applies - only emptiness and duplicates do
- If hit programmatically, compute slugifyCustomProviderName(label) first and assert it is non-empty and unused
Example fix
// before - rely on the throw inside submitProvider
await submitProvider();
// after - gate the call on the same conditions the form uses
const slug = slugifyCustomProviderName(label);
if (!slug || existingSlugs.includes(slug) || (!initial && BUILTIN_RESERVED_SLUGS.includes(slug))) {
return; // field-level slugError already tells the user why
}
await submitProvider(); Defensive patterns
Strategy: validation
Validate before calling
// Reproduce the form's gate before submitting programmatically
const slug = slugifyCustomProviderName(label);
const slugError = !slug
? t('settings.ai.slugMissingError')
: existingSlugs.includes(slug)
? t('settings.ai.slugInUseError')
: !initial && BUILTIN_RESERVED_SLUGS.includes(slug)
? t('settings.ai.slugReservedError')
: null;
if (slugError) { setSubmitError(slugError); return; } Prevention
- Give custom providers distinctive labels - built-in names like 'openai' are reserved for new entries
- Remember editing an existing entry skips only the reserved check; duplicate and empty slugs still block
- Labels made solely of emoji/punctuation slugify to nothing - include at least one word character
When it happens
Trigger: A custom-provider label whose slugified form is empty (label is only emoji/punctuation/spaces); a label that slugifies identically to an existing custom provider's slug; or creating a new custom provider whose label collides with a built-in slug (e.g. 'openai') - reserved check is skipped when editing an existing entry.
Common situations: Users naming a provider 'OpenAI' or 'Anthropic' trying to override a built-in; two providers named 'My GPT' and 'my-gpt'; labels in scripts/emoji that produce no slug characters; UI state where the inline error is set but the disabled Save is bypassed (double-click race before re-render).
Related errors
- OpenHuman uses the session JWT — keys are not configurable h
- Endpoint must start with http:// or https://
- Could not reach ${upserted.label}: ${msg}
- mascot manifest: missing mascots array
- mascot manifest: no renderable mascots
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/46ed6363a03f2172.
Report an issue: GitHub.