tinyhumansai/openhuman · warning
settings.ai.slugMissingError | settings.ai.slugInUseError |
Error message
settings.ai.slugMissingError | settings.ai.slugInUseError | settings.ai.slugReservedError
What it means
submitProvider re-throws a precomputed slugError before doing anything else: the custom provider slug must be non-empty (slugMissingError), must not collide with another provider's slug (slugInUseError), and — when creating, not editing — must not match a builtin (slugReservedError, from BUILTIN_RESERVED_SLUGS).
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 a221052e0d)
Solutions
- Enter a unique, non-empty slug that does not match a builtin provider name
- Rename or delete the colliding custom provider first
- Check the live slugError indicator next to the field before submitting
Defensive patterns
Strategy: validation
Validate before calling
// Compute the same three checks before enabling submit:
const slugOk =
slug.trim().length > 0 &&
!existingSlugs.includes(slug) &&
(isEditing || !BUILTIN_RESERVED_SLUGS.includes(slug));
if (!slugOk) { /* disable submit and show which rule failed */ } Type guard
const isUsableSlug = ( slug: string, existing: readonly string[], reserved: readonly string[], isEdit: boolean ): boolean => slug.trim().length > 0 && !existing.includes(slug) && (isEdit || !reserved.includes(slug));
Try / catch
try {
await submitProvider({ skipProbe });
} catch (e) {
if (e instanceof Error && e.message === slugError) {
// keep dialog open focused on the slug field
return;
}
throw e;
} Prevention
- Show the reserved-slug list (or autocomplete around it) in the form UI
- Auto-suggest a slug derived from the label, checked for uniqueness live
- Remember reserved-slug collision only applies when creating, not editing
When it happens
Trigger: Submitting the custom-provider form with an empty slug, a slug already used by an existing entry, or a slug matching a reserved builtin name.
Common situations: User duplicates an existing provider config and forgets to rename the slug; tries to shadow a builtin provider by reusing its slug.
Related errors
- Endpoint must start with http:// or https://
- Finish choosing how OpenHuman runs (tap Continue on the setu
- OpenHuman could not reach its remote (cloud) runtime. Check
- agentTeamApi: ${label} must be a positive integer
- agentTeamApi.get: teamId is required
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/054f14cfa2d22243.
Report an issue: GitHub.