Merge pull request #33895 from overleaf/cd-pyodide-unsupported-module-message

Improve error messaging for python modules unsupported by Pyodide

GitOrigin-RevId: 038c672ad9da46ea6d4640b8ed37426c92d22e72
This commit is contained in:
Chris Dryden
2026-06-02 08:07:01 +00:00
committed by Copybot
parent b8067723b6
commit db1deb1617
2 changed files with 57 additions and 1 deletions
@@ -31,6 +31,15 @@ function classifyErrorType(errorMessage: string): ExecutionErrorType {
return 'generic'
}
function moduleNotFoundHelpMessage(): string {
return (
"Note: Only Pyodide's built-in packages are available in the browser. " +
'Packages installed via pip cannot be used here. ' +
'See https://pyodide.org/en/stable/usage/packages-in-pyodide.html ' +
'for the list of supported packages.'
)
}
function ensureDirectoryExists(fs: PyodideFS, filePath: string) {
const directory = path.dirname(filePath)
if (directory === '.' || directory === '/') {
@@ -221,7 +230,12 @@ async function handleRunCode(msg: RunCodeRequest) {
if (runError) {
const errorMessage =
runError instanceof Error ? runError.message : String(runError)
postFailure('stderr', errorMessage, classifyErrorType(errorMessage))
const errorType = classifyErrorType(errorMessage)
const fullMessage =
errorType === 'ModuleNotFoundError'
? `${errorMessage}\n${moduleNotFoundHelpMessage()}`
: errorMessage
postFailure('stderr', fullMessage, errorType)
return
}
@@ -257,6 +257,9 @@ describe('<PythonOutputPane />', function () {
'have.class',
'ide-redesign-python-output-pane-line-stderr'
)
cy.findByText("Only Pyodide's built-in packages", { exact: false }).should(
'not.exist'
)
})
it('renders the interrupt message as an info line', function () {
@@ -380,4 +383,43 @@ describe('<PythonOutputPane />', function () {
)
cy.findByText('hello from tomli').should('exist')
})
it('augments ModuleNotFoundError output with help text about supported Pyodide packages', function () {
const executablePythonFileContents =
'import this_module_does_not_exist_in_pyodide\n'
const projectFiles = {
[pythonExecutableScript.filename]: executablePythonFileContents,
}
const ProjectProvider = makeProjectProvider(projectFiles)
cy.mount(
<EditorProviders
scope={{
editor: {
sharejs_doc: {
doc_id: pythonExecutableScript.file_id,
getSnapshot: () => executablePythonFileContents,
},
currentDocumentId: pythonExecutableScript.file_id,
openDocName: pythonExecutableScript.filename,
},
}}
providers={{ FileTreePathProvider, ProjectProvider }}
>
<PythonExecutionProvider>
<PythonOutputPane />
</PythonExecutionProvider>
</EditorProviders>
)
cy.findByRole('button', { name: 'Run Python code' })
.should('not.be.disabled')
.click()
cy.findByText('ModuleNotFoundError', { exact: false }).should('exist')
cy.findByText("Only Pyodide's built-in packages", { exact: false }).should(
'have.class',
'ide-redesign-python-output-pane-line-stderr'
)
})
})