Skip to content

Commit 79e8c72

Browse files
committed
Fix "no tasks defined" issue (fix #1681)
1 parent e615736 commit 79e8c72

File tree

8 files changed

+172
-16
lines changed

8 files changed

+172
-16
lines changed

.changeset/eleven-eels-draw.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"trigger.dev": patch
3+
---
4+
5+
Fix "No tasks defined" issue because of misconfigured dir search paths. Also improve errors around no files or no tasks found during in dev"

packages/cli-v3/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@
120120
"terminal-link": "^3.0.0",
121121
"tiny-invariant": "^1.2.0",
122122
"tinyexec": "^0.3.1",
123-
"tinyglobby": "^0.2.2",
123+
"tinyglobby": "^0.2.10",
124124
"ws": "^8.18.0",
125125
"xdg-app-paths": "^8.3.0",
126126
"zod": "3.23.8",

packages/cli-v3/src/build/bundle.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import {
1818
} from "./packageModules.js";
1919
import { buildPlugins } from "./plugins.js";
2020
import { createEntryPointManager } from "./entryPoints.js";
21+
import { cliLink, prettyError } from "../utilities/cliOutput.js";
22+
import { SkipLoggingError } from "../cli/common.js";
2123

2224
export interface BundleOptions {
2325
target: BuildTarget;
@@ -71,6 +73,29 @@ export async function bundleWorker(options: BundleOptions): Promise<BundleResult
7173
}
7274
);
7375

76+
if (entryPointManager.entryPoints.length === 0) {
77+
const errorMessageBody = `
78+
Dirs config:
79+
${resolvedConfig.dirs.join("\n- ")}
80+
81+
Search patterns:
82+
${entryPointManager.patterns.join("\n- ")}
83+
84+
Possible solutions:
85+
1. Check if the directory paths in your config are correct
86+
2. Verify that your files match the search patterns
87+
3. Update the search patterns in your config
88+
`.replace(/^ {6}/gm, "");
89+
90+
prettyError(
91+
"No trigger files found",
92+
errorMessageBody,
93+
cliLink("View the config docs", "https://trigger.dev/docs/config/config-file")
94+
);
95+
96+
throw new SkipLoggingError();
97+
}
98+
7499
let initialBuildResult: (result: esbuild.BuildResult) => void;
75100
const initialBuildResultPromise = new Promise<esbuild.BuildResult>(
76101
(resolve) => (initialBuildResult = resolve)

packages/cli-v3/src/build/entryPoints.ts

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import { BuildTarget } from "@trigger.dev/core/v3";
22
import { ResolvedConfig } from "@trigger.dev/core/v3/build";
33
import * as chokidar from "chokidar";
4-
import { glob } from "tinyglobby";
4+
import { glob, escapePath, isDynamicPattern } from "tinyglobby";
55
import { logger } from "../utilities/logger.js";
66
import { deployEntryPoints, devEntryPoints, telemetryEntryPoint } from "./packageModules.js";
77

88
type EntryPointManager = {
99
entryPoints: string[];
10+
patterns: string[];
11+
ignorePatterns: string[];
1012
watcher?: chokidar.FSWatcher;
1113
stop: () => Promise<void>;
1214
};
@@ -34,10 +36,22 @@ export async function createEntryPointManager(
3436
onEntryPointsChange?: (entryPoints: string[]) => Promise<void>
3537
): Promise<EntryPointManager> {
3638
// Patterns to match files
37-
const patterns = dirs.flatMap((dir) => [`${dir}/**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}`]);
39+
const patterns = dirs.flatMap((dir) => [
40+
`${
41+
isDynamicPattern(dir)
42+
? `${dir}/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}`
43+
: `${escapePath(dir)}/**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}`
44+
}`,
45+
]);
3846

3947
// Patterns to ignore
40-
const ignorePatterns = config.ignorePatterns ?? DEFAULT_IGNORE_PATTERNS;
48+
let ignorePatterns = config.ignorePatterns ?? DEFAULT_IGNORE_PATTERNS;
49+
ignorePatterns = ignorePatterns.concat([
50+
"**/node_modules/**",
51+
"**/.git/**",
52+
"**/.trigger/**",
53+
"**/.next/**",
54+
]);
4155

4256
async function getEntryPoints() {
4357
// Get initial entry points
@@ -47,6 +61,10 @@ export async function createEntryPointManager(
4761
cwd: config.workingDir,
4862
});
4963

64+
if (entryPoints.length === 0) {
65+
return [];
66+
}
67+
5068
// Add required entry points
5169
if (config.configFile) {
5270
entryPoints.push(config.configFile);
@@ -80,7 +98,12 @@ export async function createEntryPointManager(
8098
let watcher: chokidar.FSWatcher | undefined;
8199

82100
if (watch && onEntryPointsChange) {
83-
logger.debug("Watching entry points for changes", { dirs, cwd: config.workingDir });
101+
logger.debug("Watching entry points for changes", {
102+
dirs,
103+
cwd: config.workingDir,
104+
patterns,
105+
ignorePatterns,
106+
});
84107
// Watch the parent directories
85108
watcher = chokidar.watch(patterns, {
86109
ignored: ignorePatterns,
@@ -121,6 +144,8 @@ export async function createEntryPointManager(
121144
return {
122145
entryPoints: initialEntryPoints,
123146
watcher,
147+
patterns,
148+
ignorePatterns,
124149
stop: async () => {
125150
await watcher?.close();
126151
},

packages/cli-v3/src/dev/workerRuntime.ts

Lines changed: 82 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import { WebSocket } from "partysocket";
1919
import { ClientOptions, WebSocket as wsWebSocket } from "ws";
2020
import { CliApiClient } from "../apiClient.js";
2121
import { DevCommandOptions } from "../commands/dev.js";
22-
import { chalkError, chalkTask } from "../utilities/cliOutput.js";
22+
import { chalkError, chalkTask, cliLink, prettyError } from "../utilities/cliOutput.js";
2323
import { resolveDotEnvVars } from "../utilities/dotEnv.js";
2424
import { eventBus } from "../utilities/eventBus.js";
2525
import { logger } from "../utilities/logger.js";
@@ -189,10 +189,15 @@ class DevWorkerRuntime implements WorkerRuntime {
189189
throw new Error("Could not initialize worker");
190190
}
191191

192-
const issues = validateWorkerManifest(backgroundWorker.manifest);
192+
const validationIssue = validateWorkerManifest(backgroundWorker.manifest);
193+
194+
if (validationIssue) {
195+
prettyError(
196+
generationValidationIssueHeader(validationIssue),
197+
generateValidationIssueMessage(validationIssue, backgroundWorker.manifest!, manifest),
198+
generateValidationIssueFooter(validationIssue)
199+
);
193200

194-
if (issues.length > 0) {
195-
issues.forEach((issue) => logger.error(issue));
196201
stop();
197202
return;
198203
}
@@ -352,22 +357,90 @@ function gatherProcessEnv() {
352357
return Object.fromEntries(Object.entries($env).filter(([key, value]) => value !== undefined));
353358
}
354359

355-
function validateWorkerManifest(manifest: WorkerManifest): string[] {
356-
const issues: string[] = [];
360+
type ValidationIssue =
361+
| {
362+
type: "duplicateTaskId";
363+
duplicationTaskIds: string[];
364+
}
365+
| {
366+
type: "noTasksDefined";
367+
};
368+
369+
function validateWorkerManifest(manifest: WorkerManifest): ValidationIssue | undefined {
370+
const issues: ValidationIssue[] = [];
357371

358372
if (!manifest.tasks || manifest.tasks.length === 0) {
359-
issues.push("No tasks defined. Make sure you are exporting tasks.");
373+
return { type: "noTasksDefined" };
360374
}
361375

362376
// Check for any duplicate task ids
363377
const taskIds = manifest.tasks.map((task) => task.id);
364378
const duplicateTaskIds = taskIds.filter((id, index) => taskIds.indexOf(id) !== index);
365379

366380
if (duplicateTaskIds.length > 0) {
367-
issues.push(createDuplicateTaskIdOutputErrorMessage(duplicateTaskIds, manifest.tasks));
381+
return { type: "duplicateTaskId", duplicationTaskIds: duplicateTaskIds };
382+
}
383+
384+
return undefined;
385+
}
386+
387+
function generationValidationIssueHeader(issue: ValidationIssue) {
388+
switch (issue.type) {
389+
case "duplicateTaskId": {
390+
return `Duplicate task ids detected`;
391+
}
392+
case "noTasksDefined": {
393+
return `No tasks exported from your trigger files`;
394+
}
368395
}
396+
}
369397

370-
return issues;
398+
function generateValidationIssueFooter(issue: ValidationIssue) {
399+
switch (issue.type) {
400+
case "duplicateTaskId": {
401+
return cliLink("View the task docs", "https://trigger.dev/docs/tasks/overview");
402+
}
403+
case "noTasksDefined": {
404+
return cliLink("View the task docs", "https://trigger.dev/docs/tasks/overview");
405+
}
406+
}
407+
}
408+
409+
function generateValidationIssueMessage(
410+
issue: ValidationIssue,
411+
manifest: WorkerManifest,
412+
buildManifest: BuildManifest
413+
) {
414+
switch (issue.type) {
415+
case "duplicateTaskId": {
416+
return createDuplicateTaskIdOutputErrorMessage(issue.duplicationTaskIds, manifest.tasks);
417+
}
418+
case "noTasksDefined": {
419+
return `
420+
Files:
421+
${buildManifest.files.map((file) => file.entry).join("\n")}
422+
423+
Make sure you have at least one task exported from your trigger files.
424+
425+
You may have defined a task and forgot to add the export statement:
426+
427+
\`\`\`ts
428+
import { task } from "@trigger.dev/sdk/v3";
429+
430+
👇 Don't forget this
431+
export const myTask = task({
432+
id: "myTask",
433+
async run() {
434+
// Your task logic here
435+
}
436+
});
437+
\`\`\`
438+
`.replace(/^ {8}/gm, "");
439+
}
440+
default: {
441+
return `Unknown validation issue: ${issue}`;
442+
}
443+
}
371444
}
372445

373446
function createDuplicateTaskIdOutputErrorMessage(

pnpm-lock.yaml

Lines changed: 21 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { task } from "@trigger.dev/sdk/v3";
2+
3+
const helloWorld = task({
4+
id: "helloWorld",
5+
async run() {
6+
console.log("Hello World!");
7+
},
8+
});

references/v3-catalog/trigger.config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export default defineConfig({
1818
instrumentations: [new OpenAIInstrumentation()],
1919
additionalFiles: ["wrangler/wrangler.toml"],
2020
maxDuration: 3600,
21+
dirs: ["./src/trigger"],
2122
retries: {
2223
enabledInDev: true,
2324
default: {

0 commit comments

Comments
 (0)