Repository navigation
FastBoot: docs header search box crashes ember serve on routes outside docs #1711
Copy link
Copy link
Open
Description
Description
When the docs app runs with FastBoot in development, visiting any page outside the docs route throws an autotracking assertion while the page renders. This includes the home page /. The error isn't handled, so it stops the ember serve process.
Error: Assertion Failed: You attempted to update `_records` on `<DocsStoreService:ember203>`, but it had already been used previously in the same computation. Attempting to update a value after using it in a computation can cause logical errors, infinite revalidation bugs, and performance issues, and is not supported.
`_records` was first used:
- While rendering:
{{outlet}} for -top-level
-top-level
{{outlet}} for application
application
docs-header
docs-header/search-box
The update's stack trace goes through DocsStoreService._loadPayload → _fetchProject → findRecord, called from the DocsHeaderSearchBox constructor.
Pages under /docs work. Production builds also prerender fine with prember, likely because assertions are stripped there.
Steps to reproduce
- Use the usual setup, where
application.hbsrenders<DocsHeader />and the index route has no model hook. - Install
ember-cli-fastbootandpremberas v11 requires, and runember serve. - Request
/so FastBoot renders it (for example,curl -H 'Accept: text/html' http://localhost:4200/). - The assertion above is thrown and the dev server exits.
Cause
DocsHeaderSearchBox's constructor callsthis.fetchProject.perform(), which callsdocsStore.findRecord('project', …)during render.findRecordreads the tracked_recordsto check for an existing record.- In FastBoot,
_fetchProjectreads the JSON withfs.readFileSyncand has noawaitbeforethis._loadPayload(payload). So_loadPayloadruns synchronously, in the same render that just read_records, and itsthis._records = { ...this._records }sets the property that was just read. - In the browser, the
await fetch(…)defers the update, so the problem doesn't show up there. /docspages avoid it becauseroutes/docs.jsloads the project inmodel()before anything renders.
Workaround
Load the project in the app's application route, as routes/docs.js does:
import Route from '@ember/routing/route';
import { service } from '@ember/service';
import config from 'my-docs-app/config/environment';
export default class ApplicationRoute extends Route {
@service docsStore;
model() {
return this.docsStore.findRecord(
'project',
config['ember-cli-addon-docs'].projectName,
);
}
}Possible fixes
- Defer the store update in the FastBoot branch of
_fetchProject, for example withawait Promise.resolve()before_loadPayload, so it never happens mid-render. - Skip loading the project in the search box's constructor in FastBoot. Search is only interactive in the browser.
- Load the project in an application-level hook in the addon, so every page has it before the header renders.
Environment
- ember-cli-addon-docs 11.0.0
- ember-source 6.7.0
- ember-cli-fastboot 6.0.0
- prember 2.1.0
- ember-concurrency 5.1.0
- @embroider/compat 3.9.3 and @embroider/webpack 4.1.0
- Node 22.21.1
Metadata
Metadata
Assignees
Labels
No labels
Activity