Skip to content

Commit

Permalink
Add file location to errors in build (#5743)
Browse files Browse the repository at this point in the history
* feat(errors): Add file location where error happened during build for user-generated errors

* chore: changeset

* fix(errors): Only add information if the error is in a compatible shape

* feat(errors): Add hint to throw Error objects instead of other types for better information

* test(errors): Add test to make sure errors in build have the error location

* chore(lockfile): Update lockfile

* chore: misc text fixes
  • Loading branch information
Princesseuh committed Jan 4, 2023
1 parent 000d3e6 commit 2a57864
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/shaggy-melons-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Add error location during build for user-generated errors
12 changes: 11 additions & 1 deletion packages/astro/src/core/build/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type {
ComponentInstance,
EndpointHandler,
RouteType,
SSRError,
SSRLoadedRenderer,
} from '../../@types/astro';
import { getContentPaths } from '../../content/index.js';
Expand All @@ -22,6 +23,7 @@ import {
import { runHookBuildGenerated } from '../../integrations/index.js';
import { BEFORE_HYDRATION_SCRIPT_ID, PAGE_SCRIPT_ID } from '../../vite-plugin-scripts/index.js';
import { call as callEndpoint, throwIfRedirectNotAllowed } from '../endpoint/index.js';
import { AstroError } from '../errors/index.js';
import { debug, info } from '../logger/core.js';
import { createEnvironment, createRenderContext, renderPage } from '../render/index.js';
import { callGetStaticPaths } from '../render/route-cache.js';
Expand Down Expand Up @@ -397,7 +399,15 @@ async function generatePath(
encoding = result.encoding;
}
} else {
const response = await renderPage(mod, ctx, env);
let response: Response;
try {
response = await renderPage(mod, ctx, env);
} catch (err) {
if (!AstroError.is(err) && !(err as SSRError).id && typeof err === 'object') {
(err as SSRError).id = pageData.component;
}
throw err;
}
throwIfRedirectNotAllowed(response, opts.settings.config);
// If there's no body, do nothing
if (!response.body) return;
Expand Down
15 changes: 12 additions & 3 deletions packages/astro/src/core/errors/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { DiagnosticCode } from '@astrojs/compiler/shared/diagnostics.js';
import type { SSRError } from '../../@types/astro.js';
import { AstroErrorCodes, AstroErrorData } from './errors-data.js';

/**
Expand Down Expand Up @@ -72,9 +73,17 @@ function getLineOffsets(text: string) {

/** Coalesce any throw variable to an Error instance. */
export function createSafeError(err: any): Error {
return err instanceof Error || (err && err.name && err.message)
? err
: new Error(JSON.stringify(err));
if (err instanceof Error || (err && err.name && err.message)) {
return err;
} else {
const error = new Error(JSON.stringify(err));

(
error as SSRError
).hint = `To get as much information as possible from your errors, make sure to throw Error objects instead of \`${typeof err}\`. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error for more information.`;

return error;
}
}

export function normalizeLF(code: string) {
Expand Down
22 changes: 22 additions & 0 deletions packages/astro/test/error-build-location.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { expect } from 'chai';
import { loadFixture } from './test-utils.js';

describe('Errors information in build', () => {
/** @type {import('./test-utils').Fixture} */
let fixture;

it('includes the file where the error happened', async () => {
fixture = await loadFixture({
root: './fixtures/error-build-location',
});

let errorContent;
try {
await fixture.build();
} catch (e) {
errorContent = e;
}

expect(errorContent.id).to.equal('src/pages/index.astro');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { defineConfig } from 'astro/config';

export default defineConfig({});
15 changes: 15 additions & 0 deletions packages/astro/test/fixtures/error-build-location/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "@test/error-non-error",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "astro dev",
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"astro": "workspace:*"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="astro/client" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
throw new Error("I'm happening in build!")
---
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 2a57864

Please sign in to comment.