I was working on a Joke API for my SvelteKit project with Bun as the runtime and TypeScript as the programming language. My Joke API involves getting one random line from a text file containing 363 dad jokes. For that I obviously had to read the file. So I implemented that method and it worked splendidly…except for one part. The file reader couldn’t find the file. The file location I put in was ./jokes.txt
, which was exactly where it was. However, the file reader said that it just can’t find it. I thought that because I was using Bun.file
to read the file that it was causing issues because Bun is relatively new, so I tried readFileSync
and that didn’t work either.
Here’s my code:
import { readFileSync } from "fs";
import { db } from "$lib/db";
import { sql } from "drizzle-orm";
import { sqliteTable, integer, text } from 'drizzle-orm/sqlite-core';
export async function GET() {
let file = readFileSync("./jokes.txt", "utf-8");
const jokes = file.split("n");
const today = new Date();
const jokecords = sqliteTable("jokecords", {
id: integer("id").primaryKey(),
joke: text("joke"),
month: text("month"),
day: text("day")
});
const matches = await db.select().from(jokecords).where(
sql`month = ${today.getMonth().toString()} and day = ${today.getDay().toString()}`
);
let joke;
if (matches.length > 0) {
joke = matches[0];
}
else {
joke = jokes[Math.floor(Math.random() * jokes.length)];
await db.insert(jokecords).values({
joke: joke,
month: today.getMonth().toString(),
day: today.getDay().toString()
});
}
return {
joke: joke
}
}
and this is my file structure
.sveltekit
node_modules
src
lib
db.ts
routes
api
+server.ts
jokes.txt
jokes-backup.txt
+layout.svelte
+page.svelte
app.d.ts
app.html
app.pcss
static
.gitignore
.npmrc
bun.lockb
package.json
postcss.config.cjs
README.md
svelte.config.js
tailwind.config.cjs
tsconfig.json
vite.config.ts
2
Answers
readFileSync
can runs in an unespecified way because it depends on the relative path of the execution of code, not your current file. The best way to avoid this is to always compare the location of the code file with the execution runtime and resolve it, like:If
readFileSync
throws anENOENT
there is point in insisting the file exists. It just doesn’t. And most of the time the error happens because the path you are using does not point to the location you think it does.The relative path
./jokes.txt
does not point to the directory where the calling file is located but to the current working directory of the process. And that is — most certainly — not deep in your filestructure. Try logging aprocess.cwd()
to see what the current working directory is.You could also use
path.resolve('./jokes.txt')
to see, where that relative path actually resolves to. And most certainly you won’t find ajokes.txt
there.If you are really sure, you want to read a file in the same directory as your current file use
__dirname
And just some remarks unrelated to the issue
Using
readFileSync
in anasync
context kind of defeats the purpose ofasync
because it blocks execution. There is an async fs promises APII don’t know what
db
is, butuses string templates to create a query, that’s considered bad style because it may open your code to SQL injections. Use parameterized queries instead.