QuantumNous/new-api · error · Error

No models fetched from upstream

Error message

No models fetched from upstream

What it means

Thrown by formPreviewFetcher after fetchModels resolves without success or without data. The request carries type, key (only when creating), channel_id (advanced custom editing), base_url, advanced_custom, header_override, and proxy; any upstream failure to list models ends here with the backend message or this i18n fallback.

Source

Thrown at web/src/features/channels/components/drawers/channel-mutate-drawer.tsx:1482

    const type = form.getValues('type')
    const editingAdvancedCustom =
      isEditing && type === CHANNEL_TYPE_ADVANCED_CUSTOM
    if (editingAdvancedCustom && channelId === null) {
      throw new Error(t('No channel selected'))
    }
    const response = await fetchModels({
      type,
      key: isEditing ? undefined : form.getValues('key'),
      channel_id: editingAdvancedCustom ? channelId || undefined : undefined,
      base_url: form.getValues('base_url') || '',
      advanced_custom: form.getValues('advanced_custom'),
      header_override: form.getValues('header_override'),
      proxy: form.getValues('proxy'),
    })
    if (response.success && response.data) {
      return response.data
    }
    throw new Error(response.message || t('No models fetched from upstream'))
  }, [canEditSensitive, channelId, form, isEditing, t])

  // Handle model operations
  const handleFillRelatedModels = useCallback(() => {
    if (!basicModels.length) {
      toast.info(t('No related models available for this channel type'))
      return
    }
    updateModels(basicModels)
    toast.success(
      t('Filled {{count}} related model(s)', { count: basicModels.length })
    )
  }, [basicModels, updateModels, t])

  const handleFillAllModels = useCallback(() => {
    if (!allModelsList.length) {
      toast.info(t('No models available'))
      return

View on GitHub (pinned to e2c7aa7b10)

Solutions

  1. Double-check key and base_url in the form (the exact values sent are the form fields shown in the source)
  2. Test connectivity from the backend host: curl {base_url}/v1/models with the same key and proxy
  3. Temporarily clear header_override/advanced_custom to isolate which field breaks the request
  4. Read the backend message in the error toast — it usually contains the upstream status/body

Example fix

// before
if (response.success && response.data) {
  return response.data
}
throw new Error(response.message || t('No models fetched from upstream'))
// after - distinguish empty list from failure explicitly
if (!response.success) {
  throw new Error(response.message || t('No models fetched from upstream'))
}
if (!response.data?.length) {
  throw new Error(t('No models fetched from upstream'))
}
return response.data
Defensive patterns

Strategy: try-catch

Validate before calling

if (!canEditSensitive) throw new Error(t("You don't have necessary permission"))
const key = form.getValues('key')
const needsKey = !isEditing || !!form.getValues('base_url')
if (needsKey && !key?.trim()) { toast.error(t('Please enter API key first')); return }

Type guard

const isModelList = (d: unknown): d is string[] =>
  Array.isArray(d) && d.every((m) => typeof m === 'string')

Try / catch

try {
  const response = await fetchModels({ type, key: isEditing ? undefined : form.getValues('key'), channel_id: editingAdvancedCustom ? channelId || undefined : undefined, base_url: form.getValues('base_url') || '', advanced_custom: form.getValues('advanced_custom'), header_override: form.getValues('header_override'), proxy: form.getValues('proxy') })
  if (!response.success || !response.data?.length) {
    throw new Error(response.message || t('No models fetched from upstream'))
  }
  return response.data
} catch (error) {
  toast.error(error instanceof Error ? error.message : t('No models fetched from upstream'))
  return []
}

Prevention

When it happens

Trigger: Clicking fetch models when the upstream /v1/models call fails: wrong or invalid key, unreachable base_url, bad proxy setting, header_override breaking auth, or upstream returning an empty/error payload with success=true but no data.

Common situations: Key entered but not yet saved / typo'd; base_url missing scheme or pointing at a non-OpenAI-compatible endpoint; corporate proxy field wrong so the backend cannot connect; provider renamed the models endpoint.

Related errors


AI-assisted analysis of QuantumNous/new-api@e2c7aa7b10 (2026-08-15). Data as JSON: /api/errors/f97fe609caa8e63a. Report an issue: GitHub.