Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions 5 .changeset/eleven-eels-draw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---

Fix "No tasks defined" issue because of misconfigured dir search paths. Also improve errors around no files or no tasks found during in dev"
2 changes: 1 addition & 1 deletion 2 packages/cli-v3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
"terminal-link": "^3.0.0",
"tiny-invariant": "^1.2.0",
"tinyexec": "^0.3.1",
"tinyglobby": "^0.2.2",
"tinyglobby": "^0.2.10",
"ws": "^8.18.0",
"xdg-app-paths": "^8.3.0",
"zod": "3.23.8",
Expand Down
25 changes: 25 additions & 0 deletions 25 packages/cli-v3/src/build/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
} from "./packageModules.js";
import { buildPlugins } from "./plugins.js";
import { createEntryPointManager } from "./entryPoints.js";
import { cliLink, prettyError } from "../utilities/cliOutput.js";
import { SkipLoggingError } from "../cli/common.js";

export interface BundleOptions {
target: BuildTarget;
Expand Down Expand Up @@ -71,6 +73,29 @@ export async function bundleWorker(options: BundleOptions): Promise<BundleResult
}
);

if (entryPointManager.entryPoints.length === 0) {
const errorMessageBody = `
Dirs config:
${resolvedConfig.dirs.join("\n- ")}

Search patterns:
${entryPointManager.patterns.join("\n- ")}

Possible solutions:
1. Check if the directory paths in your config are correct
2. Verify that your files match the search patterns
3. Update the search patterns in your config
`.replace(/^ {6}/gm, "");

prettyError(
"No trigger files found",
errorMessageBody,
cliLink("View the config docs", "https://trigger.dev/docs/config/config-file")
);

throw new SkipLoggingError();
}

let initialBuildResult: (result: esbuild.BuildResult) => void;
const initialBuildResultPromise = new Promise<esbuild.BuildResult>(
(resolve) => (initialBuildResult = resolve)
Expand Down
33 changes: 29 additions & 4 deletions 33 packages/cli-v3/src/build/entryPoints.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { BuildTarget } from "@trigger.dev/core/v3";
import { ResolvedConfig } from "@trigger.dev/core/v3/build";
import * as chokidar from "chokidar";
import { glob } from "tinyglobby";
import { glob, escapePath, isDynamicPattern } from "tinyglobby";
import { logger } from "../utilities/logger.js";
import { deployEntryPoints, devEntryPoints, telemetryEntryPoint } from "./packageModules.js";

type EntryPointManager = {
entryPoints: string[];
patterns: string[];
ignorePatterns: string[];
watcher?: chokidar.FSWatcher;
stop: () => Promise<void>;
};
Expand Down Expand Up @@ -34,10 +36,22 @@ export async function createEntryPointManager(
onEntryPointsChange?: (entryPoints: string[]) => Promise<void>
): Promise<EntryPointManager> {
// Patterns to match files
const patterns = dirs.flatMap((dir) => [`${dir}/**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}`]);
const patterns = dirs.flatMap((dir) => [
`${
isDynamicPattern(dir)
? `${dir}/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}`
: `${escapePath(dir)}/**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}`
}`,
]);

// Patterns to ignore
const ignorePatterns = config.ignorePatterns ?? DEFAULT_IGNORE_PATTERNS;
let ignorePatterns = config.ignorePatterns ?? DEFAULT_IGNORE_PATTERNS;
ignorePatterns = ignorePatterns.concat([
"**/node_modules/**",
"**/.git/**",
"**/.trigger/**",
"**/.next/**",
]);

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

if (entryPoints.length === 0) {
return [];
}

// Add required entry points
if (config.configFile) {
entryPoints.push(config.configFile);
Expand Down Expand Up @@ -80,7 +98,12 @@ export async function createEntryPointManager(
let watcher: chokidar.FSWatcher | undefined;

if (watch && onEntryPointsChange) {
logger.debug("Watching entry points for changes", { dirs, cwd: config.workingDir });
logger.debug("Watching entry points for changes", {
dirs,
cwd: config.workingDir,
patterns,
ignorePatterns,
});
// Watch the parent directories
watcher = chokidar.watch(patterns, {
ignored: ignorePatterns,
Expand Down Expand Up @@ -121,6 +144,8 @@ export async function createEntryPointManager(
return {
entryPoints: initialEntryPoints,
watcher,
patterns,
ignorePatterns,
stop: async () => {
await watcher?.close();
},
Expand Down
91 changes: 82 additions & 9 deletions 91 packages/cli-v3/src/dev/workerRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { WebSocket } from "partysocket";
import { ClientOptions, WebSocket as wsWebSocket } from "ws";
import { CliApiClient } from "../apiClient.js";
import { DevCommandOptions } from "../commands/dev.js";
import { chalkError, chalkTask } from "../utilities/cliOutput.js";
import { chalkError, chalkTask, cliLink, prettyError } from "../utilities/cliOutput.js";
import { resolveDotEnvVars } from "../utilities/dotEnv.js";
import { eventBus } from "../utilities/eventBus.js";
import { logger } from "../utilities/logger.js";
Expand Down Expand Up @@ -189,10 +189,15 @@ class DevWorkerRuntime implements WorkerRuntime {
throw new Error("Could not initialize worker");
}

const issues = validateWorkerManifest(backgroundWorker.manifest);
const validationIssue = validateWorkerManifest(backgroundWorker.manifest);

if (validationIssue) {
prettyError(
generationValidationIssueHeader(validationIssue),
generateValidationIssueMessage(validationIssue, backgroundWorker.manifest!, manifest),
generateValidationIssueFooter(validationIssue)
);

if (issues.length > 0) {
issues.forEach((issue) => logger.error(issue));
stop();
return;
}
Expand Down Expand Up @@ -352,22 +357,90 @@ function gatherProcessEnv() {
return Object.fromEntries(Object.entries($env).filter(([key, value]) => value !== undefined));
}

function validateWorkerManifest(manifest: WorkerManifest): string[] {
const issues: string[] = [];
type ValidationIssue =
| {
type: "duplicateTaskId";
duplicationTaskIds: string[];
}
| {
type: "noTasksDefined";
};

function validateWorkerManifest(manifest: WorkerManifest): ValidationIssue | undefined {
const issues: ValidationIssue[] = [];

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

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

if (duplicateTaskIds.length > 0) {
issues.push(createDuplicateTaskIdOutputErrorMessage(duplicateTaskIds, manifest.tasks));
return { type: "duplicateTaskId", duplicationTaskIds: duplicateTaskIds };
}

return undefined;
}

function generationValidationIssueHeader(issue: ValidationIssue) {
switch (issue.type) {
case "duplicateTaskId": {
return `Duplicate task ids detected`;
}
case "noTasksDefined": {
return `No tasks exported from your trigger files`;
}
}
}

return issues;
function generateValidationIssueFooter(issue: ValidationIssue) {
switch (issue.type) {
case "duplicateTaskId": {
return cliLink("View the task docs", "https://trigger.dev/docs/tasks/overview");
}
case "noTasksDefined": {
return cliLink("View the task docs", "https://trigger.dev/docs/tasks/overview");
}
}
}

function generateValidationIssueMessage(
issue: ValidationIssue,
manifest: WorkerManifest,
buildManifest: BuildManifest
) {
switch (issue.type) {
case "duplicateTaskId": {
return createDuplicateTaskIdOutputErrorMessage(issue.duplicationTaskIds, manifest.tasks);
}
case "noTasksDefined": {
return `
Files:
${buildManifest.files.map((file) => file.entry).join("\n")}

Make sure you have at least one task exported from your trigger files.

You may have defined a task and forgot to add the export statement:

\`\`\`ts
import { task } from "@trigger.dev/sdk/v3";

👇 Don't forget this
export const myTask = task({
id: "myTask",
async run() {
// Your task logic here
}
});
\`\`\`
`.replace(/^ {8}/gm, "");
}
default: {
return `Unknown validation issue: ${issue}`;
}
}
}

function createDuplicateTaskIdOutputErrorMessage(
Expand Down
23 changes: 21 additions & 2 deletions 23 pnpm-lock.yaml

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

8 changes: 8 additions & 0 deletions 8 references/v3-catalog/src/trigger2/helloWorld.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { task } from "@trigger.dev/sdk/v3";

const helloWorld = task({
id: "helloWorld",
async run() {
console.log("Hello World!");
},
});
1 change: 1 addition & 0 deletions 1 references/v3-catalog/trigger.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default defineConfig({
instrumentations: [new OpenAIInstrumentation()],
additionalFiles: ["wrangler/wrangler.toml"],
maxDuration: 3600,
dirs: ["./src/trigger"],
Comment thread
ericallam marked this conversation as resolved.
retries: {
enabledInDev: true,
default: {
Expand Down
Morty Proxy This is a proxified and sanitized view of the page, visit original site.