ReferenceError: [ENV] BOT_OWNER_IDS - The key must be an array, but is empty or undefined.

I am using @skyra/env-utilities and when I start up my bot, I get the error reported in the title of this post. I cannot figure out what I am missing. I have a .env.local file in my src directory. It is erroring when it gets to export const OWNERS = envParseArray('BOT_OWNER_IDS'); in my src/lib/constants.ts file. This is the contents of my src/lib/setup.ts file:
// Unless explicitly defined, set NODE_ENV as development:
// process.env.NODE_ENV ??= 'development';

import '@sapphire/plugin-api/register';
import '@sapphire/plugin-editable-commands/register';
import '@sapphire/plugin-logger/register';
import * as colorette from 'colorette';
import { type NumberString, setup, type ArrayString } from '@skyra/env-utilities';
import { join } from 'node:path';
import { inspect } from 'util';
import { rootFolder } from './constants';

// Read env var
setup(join(rootFolder, 'src', '.env'));

// Set default inspection depth
inspect.defaultOptions.depth = 1;

// Enable colorette
colorette.createColors({ useColor: true });

declare module '@skyra/env-utilities' {
interface Env {
BOT_OWNER_IDS: ArrayString;
BOT_REPORT_CHANNEL_ID: string;
MONGO_HOST: string;
MONGO_USERNAME: string;
MONGO_PASSWORD: string;
MONGO_DB: string;
MONGO_API_KEY: string;
MONGO_DB_MAX_SIZE: NumberString;
AWS_S3_BUCKET: string;
AWS_REGION: string;
}
}
// Unless explicitly defined, set NODE_ENV as development:
// process.env.NODE_ENV ??= 'development';

import '@sapphire/plugin-api/register';
import '@sapphire/plugin-editable-commands/register';
import '@sapphire/plugin-logger/register';
import * as colorette from 'colorette';
import { type NumberString, setup, type ArrayString } from '@skyra/env-utilities';
import { join } from 'node:path';
import { inspect } from 'util';
import { rootFolder } from './constants';

// Read env var
setup(join(rootFolder, 'src', '.env'));

// Set default inspection depth
inspect.defaultOptions.depth = 1;

// Enable colorette
colorette.createColors({ useColor: true });

declare module '@skyra/env-utilities' {
interface Env {
BOT_OWNER_IDS: ArrayString;
BOT_REPORT_CHANNEL_ID: string;
MONGO_HOST: string;
MONGO_USERNAME: string;
MONGO_PASSWORD: string;
MONGO_DB: string;
MONGO_API_KEY: string;
MONGO_DB_MAX_SIZE: NumberString;
AWS_S3_BUCKET: string;
AWS_REGION: string;
}
}
contents of my .env.local:
NODE_ENV=development

# Tokens
DISCORD_TOKEN=discordToken
DISCORD_CLIENT_ID=11111111
DISCORD_CLIENT_SECRET=discordSecret
DISCORD_PUBLIC_KEY=discordPubKey

# Configuration
DEFAULT_PREFIX=dmb
BOT_OWNER_IDS='49242868987990016 253018958536376321'
BOT_REPORT_CHANNEL_ID=470100327840874496

# Mongo DB Data
MONGO_HOST=some.address.mongodb.net
MONGO_USERNAME=username
MONGO_PASSWORD=password
MONGO_DB=db
MONGO_API_KEY=apiKey
MONGO_DB_MAX_SIZE=496

# AWS S3 Data
AWS_REGION=us-east-2
AWS_ACCESS_KEY_ID=awsAccessKey
AWS_SECRET_ACCESS_KEY=awsSecret
AWS_S3_BUCKET=awsBucket
NODE_ENV=development

# Tokens
DISCORD_TOKEN=discordToken
DISCORD_CLIENT_ID=11111111
DISCORD_CLIENT_SECRET=discordSecret
DISCORD_PUBLIC_KEY=discordPubKey

# Configuration
DEFAULT_PREFIX=dmb
BOT_OWNER_IDS='49242868987990016 253018958536376321'
BOT_REPORT_CHANNEL_ID=470100327840874496

# Mongo DB Data
MONGO_HOST=some.address.mongodb.net
MONGO_USERNAME=username
MONGO_PASSWORD=password
MONGO_DB=db
MONGO_API_KEY=apiKey
MONGO_DB_MAX_SIZE=496

# AWS S3 Data
AWS_REGION=us-east-2
AWS_ACCESS_KEY_ID=awsAccessKey
AWS_SECRET_ACCESS_KEY=awsSecret
AWS_S3_BUCKET=awsBucket
I am not sure what I am missing or how to resolve
Solution:
Okay so the problem is that files are required in order of lines in the file so index calls setup first, but that also first calls constants because it's above the line that calls setup. Calling constants means that envParseArray gets executed, but because setup hasn't ran yet you get the error that you do. So the fix is to split your constants file in stuff that is needed for env, and stuff that isn't needed. That way you can safely import the former in setup....
Jump to solution
7 Replies
Lioness100
Lioness1002y ago
I think the values are supposed to be separated by a space instead of a newline So it would be
BOT_OWNER_IDS='owner1 owner2 owner2'
BOT_OWNER_IDS='owner1 owner2 owner2'
Caspian Nightworth
they are separated by a space BOT_OWNER_IDS='49242868987990016 253018958536376321' I even get the same error if I just have 1 id in that list
Favna
Favna2y ago
What's the content of constants file? And where do you call setup? Also share that file please.
Caspian Nightworth
constants.ts
import { getRootData } from '@sapphire/pieces';
import { join } from 'path';
import * as os from 'node:os';
import { envParseArray } from '@skyra/env-utilities';

export const mainFolder = getRootData().root;
export const rootFolder = join(mainFolder, '..');
export const backupTime = '59 23 * * *';
export const FetchUserAgent = `Sapphire Application Commands/2.0.0 (node-fetch) ${os.platform()}/${os.release()}`;
export const RandomLoadingMessage = ['Computing...', 'Thinking...', 'Cooking some food', 'Give me a moment', 'Loading...'];
export const OWNERS = envParseArray('BOT_OWNER_IDS');
import { getRootData } from '@sapphire/pieces';
import { join } from 'path';
import * as os from 'node:os';
import { envParseArray } from '@skyra/env-utilities';

export const mainFolder = getRootData().root;
export const rootFolder = join(mainFolder, '..');
export const backupTime = '59 23 * * *';
export const FetchUserAgent = `Sapphire Application Commands/2.0.0 (node-fetch) ${os.platform()}/${os.release()}`;
export const RandomLoadingMessage = ['Computing...', 'Thinking...', 'Cooking some food', 'Give me a moment', 'Loading...'];
export const OWNERS = envParseArray('BOT_OWNER_IDS');
index.ts
import '#lib/setup';

import { schedule } from 'node-cron';
import { backupTime } from '#lib/constants';
import { MongoBackup } from '#lib/backupDB';
import { DexcomMongoClient } from './DexcomMongoClient';
import { envParseString } from '@skyra/env-utilities';

const client = new DexcomMongoClient();

const main = async () => {
try {
client.logger.info('Logging in');
await client.login();
client.logger.info('logged in');

const dexChan = await client.channels.fetch(envParseString('BOT_REPORT_CHANNEL_ID'));

// Make sure the channel is text based - why wouldn't it be?
if (dexChan?.isTextBased()) {
// Run the scheduled task that will run nightly at 11:59 pm
schedule(backupTime, () => {
backupDBProcess(dexChan);
});
}
} catch (error) {
client.logger.fatal(error);
client.destroy();
process.exit(1);
}
};

const backupDBProcess = async (channel) => {
const backupProcess = new MongoBackup(channel);

await backupProcess.backup();
// await backupProcess.threadPurge();
};

void main();
import '#lib/setup';

import { schedule } from 'node-cron';
import { backupTime } from '#lib/constants';
import { MongoBackup } from '#lib/backupDB';
import { DexcomMongoClient } from './DexcomMongoClient';
import { envParseString } from '@skyra/env-utilities';

const client = new DexcomMongoClient();

const main = async () => {
try {
client.logger.info('Logging in');
await client.login();
client.logger.info('logged in');

const dexChan = await client.channels.fetch(envParseString('BOT_REPORT_CHANNEL_ID'));

// Make sure the channel is text based - why wouldn't it be?
if (dexChan?.isTextBased()) {
// Run the scheduled task that will run nightly at 11:59 pm
schedule(backupTime, () => {
backupDBProcess(dexChan);
});
}
} catch (error) {
client.logger.fatal(error);
client.destroy();
process.exit(1);
}
};

const backupDBProcess = async (channel) => {
const backupProcess = new MongoBackup(channel);

await backupProcess.backup();
// await backupProcess.threadPurge();
};

void main();
Solution
Favna
Favna2y ago
Okay so the problem is that files are required in order of lines in the file so index calls setup first, but that also first calls constants because it's above the line that calls setup. Calling constants means that envParseArray gets executed, but because setup hasn't ran yet you get the error that you do. So the fix is to split your constants file in stuff that is needed for env, and stuff that isn't needed. That way you can safely import the former in setup.
Lioness100
Lioness1002y ago
Oh my bad, I'm viewing on mobile so it put the second id on the line below
Caspian Nightworth
thanks. i kept over looking that
Want results from more Discord servers?
Add your server