payloadcms/payload · error

Search failed

Error message

Search failed

What it means

A plain Error thrown in the Hierarchy field's client search hook (useHierarchySearch) when the admin API search fetch returns a non-ok response. The fetch targets the collection's list endpoint with a formatted admin URL and credentials included; any non-2xx aborts with this generic message.

Source

Thrown at packages/ui/src/elements/Hierarchy/Search/useHierarchySearch.ts:92

              [titlePathField]: true,
            },
            where: {
              [titleField]: { contains: query },
            },
          },
          { addQueryPrefix: true },
        )

        const url = formatAdminURL({
          apiRoute: api,
          path: `/${collectionSlug}${queryString}`,
          serverURL,
        })

        const response = await fetch(url, { credentials: 'include' })

        if (!response.ok) {
          throw new Error('Search failed')
        }

        const data = await response.json()
        const docs: SearchResult[] = (data.docs || []).map((doc: Record<string, unknown>) => ({
          ...doc,
          path: doc[titlePathField] || '',
        }))

        setResults(append ? (prev) => [...prev, ...docs] : docs)
        setHasNextPage(data.hasNextPage || false)
        setTotalDocs(data.totalDocs || 0)
        setPage(pageToFetch)
        setCurrentQuery(query)
      } catch {
        if (!append) {
          setResults([])
          setHasNextPage(false)
          setTotalDocs(0)

View on GitHub (pinned to 00c58b35c0)

Solutions

  1. Check the network response status for the search GET to identify auth vs server error.
  2. Re-authenticate if the response is 401/403 (session expired).
  3. Verify the collectionSlug and query params produce a valid admin list URL.
  4. Wrap the search call in a try/catch to degrade gracefully (show empty results / retry) instead of throwing.

Example fix

// before
const response = await fetch(url, { credentials: 'include' })
if (!response.ok) {
  throw new Error('Search failed')
}

// after — graceful degradation with status
const response = await fetch(url, { credentials: 'include' })
if (!response.ok) {
  if (response.status === 401 || response.status === 403) {
    setResults([])
    return
  }
  throw new Error(`Search failed (${response.status})`)
}
Defensive patterns

Strategy: try-catch

Validate before calling

function buildHierarchySearchURL(args: { api: string; serverURL: string; collectionSlug: string; queryString: string }): string | null {
  if (!args.collectionSlug) return null
  return formatAdminURL({ apiRoute: args.api, path: `/${args.collectionSlug}${args.queryString}`, serverURL: args.serverURL })
}

const url = buildHierarchySearchURL({ api, serverURL, collectionSlug, queryString })
if (!url) throw new Error('Cannot search: missing collection slug')

Type guard

function isSearchFailure(err: unknown): err is Error {
  return err instanceof Error && err.message === 'Search failed'
}

Try / catch

try {
  await runHierarchySearch(query)
} catch (err) {
  if (isSearchFailure(err)) {
    setResults([]) // degrade gracefully
    return
  }
  throw err
}

Prevention

When it happens

Trigger: The hierarchy relationship search issues GET /<collectionSlug>?<query> and the server returns non-2xx: 401/403 (session expired), 404 (collection slug wrong), 500 (server-side query error), or a network failure.

Common situations: Admin session expired while the hierarchy panel is open; the target collection slug changed; a server-side error in the collection's find query (e.g. malformed where filter, DB issue); CORS/proxy stripping credentials.

Related errors


AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12). Data as JSON: /api/errors/276c69d358c845ba. Report an issue: GitHub.