Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

API stores form instruments that import React, which the web app and gateway then refuse to render

Open
#1,803 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
74/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
react, typescript
Domain
api, backend

Research direction

Start in apps/api/src/instruments/instruments.service.ts:94-109 and compare its bundle validation with the React rule in packages/instrument-interpreter/src/index.ts:30-37; check how a shared package can expose that rule to the API. Run the named service test in apps/api/src/instruments/__tests__/instruments.service.test.ts and the repository-import e2e test in testing/src/specs/admin-instrument-repos.spec.ts. Done when the API rejects non-interactive bundles importing React with a 422, and both tests pass.

Written by the indexing model from the issue text.

Description

Area: API Bug Difficulty: Low Priority: Low

The API stores form instruments that every client then refuses to render. InstrumentInterpreter.interpret rejects a non-interactive instrument whose bundle imports /runtime/v1/react@* or /runtime/v1/react-dom@* (findReactImport, added in f46a257eb). That check runs only in the browser. InstrumentsService.create evaluates the same bundle server-side and validates it against $AnyInstrument, but never applies the React rule. So a form whose block imports useState, whether from an instrument repository import or a bundle upload, is accepted, stored and listed. Every attempt to open it in apps/web or the gateway then fails with "Cannot import '/runtime/v1/[email protected]/index.js' in an instrument of kind 'FORM'". The commit message says the browser is "the earliest point the two kinds can be told apart", but the API evaluates the bundle and knows its kind first.

Where

apps/api/src/instruments/instruments.service.ts:94-109:

    const result = await this.virtualizationService.eval(bundle);
    // ...
    const parseResult = await $AnyInstrument.safeParseAsync(result.value);
    if (!parseResult.success) {
      throw new UnprocessableEntityException({ /* ... */ });
    }
    const instance = parseResult.data;

compared with the client-side rule, packages/instrument-interpreter/src/index.ts:30-37:

    if (instrument.kind !== 'INTERACTIVE') {
      const reactImport = findReactImport(bundle);
      if (reactImport) {
        throw new Error(
          `Cannot import '${reactImport}' in an instrument of kind '${instrument.kind}': React is available only to interactive instruments, ...`

Reproduce

  1. In an instrument repository, add a form under lib/forms/ whose block imports { useState } from /runtime/v1/[email protected].
  2. Add the repository in apps/web (Admin > Instrument Repositories) and assign the form to a group.
  3. Start a session and open the form.

Actual: the import succeeds and the form is listed, but opening it shows the instrument error page with "React is available only to interactive instruments".
Expected: the API rejects the bundle with 422 and the same message, so the repository import reports that instrument as failed and it is never offered to users.

Tests

apps/api/src/instruments/__tests__/instruments.service.test.ts: it('should reject a non-interactive bundle that imports react, so no stored form fails in every client').

e2e, in testing/src/specs/admin-instrument-repos.spec.ts: a repository fixture form that imports react is reported as failed, not imported.

Suggested fix

Move findReactImport (or the whole kind check) into a shared package the API can import, such as @opendatacapture/instrument-utils or runtime-internal. Call it in InstrumentsService.create after the $AnyInstrument parse and throw UnprocessableEntityException with the interpreter's message. Keep the client-side check for bundles that never pass through the API, such as the playground.

Dominant language
TypeScript
Stars
119
Forks
19
Avg merge
1d 2h
Merged PRs (30d)
56

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from DouglasNeuroInformatics/OpenDataCapture

All issues in DouglasNeuroInformatics/OpenDataCapture

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.