diff --git a/CHANGELOG.md b/CHANGELOG.md
index f8f239c5..0d34479f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]
+### Fixed
+- Handle missing step gracefully ([#419](https://github.com/cucumber/react-components/pull/419))
## [24.1.1] - 2025-11-24
### Changed
diff --git a/src/components/results/TestStepOutcome.spec.tsx b/src/components/results/TestStepOutcome.spec.tsx
new file mode 100644
index 00000000..32f7b6af
--- /dev/null
+++ b/src/components/results/TestStepOutcome.spec.tsx
@@ -0,0 +1,44 @@
+import { GherkinDocument } from '@cucumber/messages'
+import { Query as CucumberQuery } from '@cucumber/query'
+import { expect } from 'chai'
+import React from 'react'
+
+import minimalSample from '../../../acceptance/minimal/minimal.js'
+import { render } from '../../../test-utils/index.js'
+import { EnvelopesProvider } from '../app/index.js'
+import { TestStepOutcome } from './TestStepOutcome.js'
+
+describe('TestStepOutcome', () => {
+ it('should still work when we cant resolve the original step', () => {
+ // omit children from gherkinDocument.feature so that Step is unresolved
+ const envelopes = minimalSample.map((envelope) => {
+ if (envelope.gherkinDocument) {
+ return {
+ gherkinDocument: {
+ ...envelope.gherkinDocument,
+ feature: {
+ ...envelope.gherkinDocument.feature,
+ children: [],
+ },
+ } as GherkinDocument,
+ }
+ }
+ return envelope
+ })
+
+ const cucumberQuery = new CucumberQuery()
+ envelopes.forEach((envelope) => cucumberQuery.update(envelope))
+
+ const [testCaseStarted] = cucumberQuery.findAllTestCaseStarted()
+ const [[testStepFinished, testStep]] =
+ cucumberQuery.findTestStepFinishedAndTestStepBy(testCaseStarted)
+
+ const { getByText } = render(
+
+
+
+ )
+
+ expect(getByText('cukes in my belly')).to.be.visible
+ })
+})
diff --git a/src/components/results/TestStepOutcome.tsx b/src/components/results/TestStepOutcome.tsx
index b8b2c60e..9290cfeb 100644
--- a/src/components/results/TestStepOutcome.tsx
+++ b/src/components/results/TestStepOutcome.tsx
@@ -1,4 +1,4 @@
-import { PickleStep, Step, TestStep, TestStepFinished } from '@cucumber/messages'
+import { PickleStep, TestStep, TestStepFinished } from '@cucumber/messages'
import React, { FC } from 'react'
import { useQueries } from '../../hooks/index.js'
@@ -48,10 +48,10 @@ const HookStepTitle: FC<{ testStep: TestStep }> = ({ testStep }) => {
const PickleStepTitle: FC<{ testStep: TestStep }> = ({ testStep }) => {
const { cucumberQuery } = useQueries()
const pickleStep = cucumberQuery.findPickleStepBy(testStep) as PickleStep
- const step = cucumberQuery.findStepBy(pickleStep) as Step
+ const step = cucumberQuery.findStepBy(pickleStep)
return (
<>
- {step.keyword.trim()}
+ {step?.keyword?.trim()}
{composePickleStepTitle(pickleStep.text, testStep.stepMatchArgumentsLists).map(
(fragment, index) => {
if (fragment.parameterTypeName) {