Skip to content

Commit ced14d0

Browse files
reakaleekclaudeCopilot
authored
Search: Fix modal rejecting valid responses with content type "docs" (#3456)
* Fix search modal rejecting valid responses with type "docs" The navigation-search contract changed the result item type value from "doc" to "docs", but the frontend Zod schemas still enumerated ['doc', 'api'], causing SearchResponse.parse() to throw on every result item and surface "Error loading search results" even for healthy 200 responses. Also adds a console.error + logError branch for non-ApiError query failures so ZodError/parse mismatches are no longer completely silent. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> * Fix search schema: rename type → content_type with value 'docs' --------- Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
1 parent e010a12 commit ced14d0

5 files changed

Lines changed: 29 additions & 10 deletions

File tree

src/Elastic.Documentation.Site/Assets/web-components/ModalSearch/ModalSearchResultsList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,9 +178,9 @@ const ModalSearchResultRow = ({
178178
return result.parents.map((p) => p.title)
179179
}
180180

181-
const typePrefix = result.type === 'api' ? 'API' : 'Docs'
181+
const typePrefix = 'Docs'
182182
return [typePrefix, ...result.parents.slice(1).map((p) => p.title)]
183-
}, [result.type, result.parents])
183+
}, [result.parents])
184184

185185
return (
186186
<a

src/Elastic.Documentation.Site/Assets/web-components/ModalSearch/useModalSearchQuery.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { config } from '../../config'
2-
import { logInfo, logWarn } from '../../telemetry/logging'
2+
import { logError, logInfo, logWarn } from '../../telemetry/logging'
33
import {
44
ATTR_NAVIGATION_SEARCH_QUERY,
55
ATTR_NAVIGATION_SEARCH_QUERY_LENGTH,
@@ -36,7 +36,7 @@ const SearchResultItemParent = z.object({
3636
})
3737

3838
const SearchResultItem = z.object({
39-
type: z.enum(['doc', 'api']),
39+
content_type: z.enum(['docs']),
4040
url: z.string(),
4141
title: z.string(),
4242
description: z.string(),
@@ -189,6 +189,14 @@ export const useModalSearchQuery = () => {
189189
'error.message': query.error.message,
190190
})
191191
}
192+
} else if (query.error) {
193+
const err = query.error as Error
194+
logError('modal_search_parse_error', {
195+
[ATTR_NAVIGATION_SEARCH_QUERY]: debouncedSearchTerm,
196+
[ATTR_ERROR_TYPE]: err.name,
197+
'error.message': err.message,
198+
})
199+
console.error('[modal-search] failed to parse search response', err)
192200
}
193201
}, [query.error, debouncedSearchTerm])
194202

src/Elastic.Documentation.Site/Assets/web-components/NavigationSearch/NavigationSearchTelemetry.test.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,15 @@ const mockSearchResults = {
3232
title: 'Elasticsearch Guide',
3333
description: 'Learn about Elasticsearch',
3434
score: 0.95,
35-
type: 'doc' as const,
35+
content_type: 'docs' as const,
3636
parents: [{ title: 'Docs' }, { title: 'Elasticsearch' }],
3737
},
3838
{
3939
url: '/docs/kibana/dashboard',
4040
title: 'Kibana Dashboard',
4141
description: 'Create dashboards',
4242
score: 0.85,
43-
type: 'doc' as const,
43+
content_type: 'docs' as const,
4444
parents: [{ title: 'Docs' }, { title: 'Kibana' }],
4545
},
4646
],

src/Elastic.Documentation.Site/Assets/web-components/NavigationSearch/SearchResultsList.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,9 +158,9 @@ const SearchResultRow = ({
158158
return result.parents.map((p) => p.title)
159159
}
160160

161-
const typePrefix = result.type === 'api' ? 'API' : 'Docs'
161+
const typePrefix = 'Docs'
162162
return [typePrefix, ...result.parents.slice(1).map((p) => p.title)]
163-
}, [result.type, result.parents])
163+
}, [result.parents])
164164

165165
return (
166166
<a

src/Elastic.Documentation.Site/Assets/web-components/NavigationSearch/useNavigationSearchQuery.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { config } from '../../config'
2-
import { logInfo, logWarn } from '../../telemetry/logging'
2+
import { logError, logInfo, logWarn } from '../../telemetry/logging'
33
import {
44
ATTR_NAVIGATION_SEARCH_QUERY,
55
ATTR_NAVIGATION_SEARCH_QUERY_LENGTH,
@@ -40,7 +40,7 @@ const SearchResultItemParent = z.object({
4040
})
4141

4242
const SearchResultItem = z.object({
43-
type: z.enum(['doc', 'api']),
43+
content_type: z.enum(['docs']),
4444
url: z.string(),
4545
title: z.string(),
4646
description: z.string(),
@@ -203,6 +203,17 @@ export const useNavigationSearchQuery = () => {
203203
'error.message': query.error.message,
204204
})
205205
}
206+
} else if (query.error) {
207+
const err = query.error as Error
208+
logError('navigation_search_parse_error', {
209+
[ATTR_NAVIGATION_SEARCH_QUERY]: debouncedSearchTerm,
210+
[ATTR_ERROR_TYPE]: err.name,
211+
'error.message': err.message,
212+
})
213+
console.error(
214+
'[navigation-search] failed to parse search response',
215+
err
216+
)
206217
}
207218
}, [query.error, debouncedSearchTerm])
208219

0 commit comments

Comments
 (0)