tscord icon indicating copy to clipboard operation
tscord copied to clipboard

[Bug] Mikro-ORM return "Cannot read properties of undefined"

Open Mr-Artemus opened this issue 1 year ago • 3 comments

What happened?

When using MySQL, Mikro-ORM can't create migration due the following error :

TypeError: Cannot read properties of undefined (reading 'BOT_OWNER_ID')
    at Object.<anonymous> (C:\Users\Josh\Documents\Projects\RoseBot\src\configs\general.ts:8:15)
    at Module._compile (node:internal/modules/cjs/loader:1546:14)
    at Module.m._compile (C:\Users\Josh\Documents\Projects\RoseBot\node_modules\ts-node\src\index.ts:1618:23)
    at node:internal/modules/cjs/loader:1698:10
    at Object.require.extensions.<computed> [as .ts] (C:\Users\Josh\Documents\Projects\RoseBot\node_modules\ts-node\src\index.ts:1621:12)
    at Module.load (node:internal/modules/cjs/loader:1303:32)
    at Function._load (node:internal/modules/cjs/loader:1117:12)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:218:24)
    at Module.require (node:internal/modules/cjs/loader:1325:12)

Credit : @JoshCantCode Cf : Discord support thread

Reproduction

  1. Init a new bot
  2. Setup .env file
  3. Change database config to use a MySQL database
  4. Run any Mikro-ORM command

Code of Conduct

  • [ ] I agree to follow this project's Code of Conduct

Mr-Artemus avatar Jan 28 '25 18:01 Mr-Artemus

Update to this. It seems to not only be a MySQL issue. Just tried creating one with Postgres and it also occurs! Doesn't really help much but at least we know the issue isn't caused by just MySQL

JoshCantCode avatar Mar 26 '25 20:03 JoshCantCode

I’ve personally tested this with Postgres, but the same error persists. It seems that when running mikro-orm migration:* commands, the .env file isn’t loaded properly—even though the repository follows the recommended approach from MikroORM’s official documentation.

The relevant changes in tscord were introduced in:

However, even in a fresh tscord project, the .env file fails to load correctly—at least in:

And I assume other part of the project might also need modification as long as @env is involved further. It looks like mikro-orm cannot properly read tsconfig.json therefore paths in compilerOptions cannot be processed or loaded.

I’d be happy to open a PR with the proposed changes (for demonstration, here I only show the modified api.ts, but to make it work, similar changes in general.ts are also needed). However, I’m unsure if this adjustment aligns with the original intent of using @env or maintains the type constraints properly.

Before

import { env } from '@/env'

export const apiConfig: APIConfigType = {

	enabled: false, // is the API server enabled or not
	port: env.API_PORT || 4000,
}

After

import 'dotenv/config'

import process from 'node:process'

// import { env } from '@/env'

const env = process.env

export const apiConfig: APIConfigType = {

	enabled: false, // is the API server enabled or not
	port: ((env.API_PORT) as unknown) as number || 4000, // very bad type casting ;(
}

These are not elegant edits but in the meantime you get a workaround to make it through.

@barthofu, let me know if you’d like me to proceed or if there’s a preferred way to handle this.

ghost avatar Apr 30 '25 21:04 ghost

There’s a circular dependency: environment.ts imports from @/configs, and configs import env, causing generalConfig to be undefined. Fix: remove the config imports from environment.ts and compute needed values inline.

In environment.ts

import process from 'node:process'

import { cleanEnv, num, str } from 'envalid'

// Remove the imports that cause circular dependency
// import { apiConfig, generalConfig, mikroORMConfig } from '@/configs'

Then (still in environment.ts)

// Move the config-dependent logic to where it's actually called
// This will be called from main.ts after all configs are loaded
export function checkEnvironmentVariables() {
	// Import dynamically to avoid circular dependency
	const { apiConfig, generalConfig, mikroORMConfig } = require('@/configs')
	...

In main.ts, changing from

async function init() {
	const logger = await resolveDependency(Logger)

	// check environment variables
	checkEnvironmentVariables()
        ...

to

async function init() {
	const logger = await resolveDependency(Logger)

	// check environment variables
	await checkEnvironmentVariables()
        ...

ghost avatar Oct 26 '25 18:10 ghost