2 examples

Variable shadowing

Inner variable hides an outer one, leading to confusion or bugs.

[ FAQ1 ]

What is variable shadowing?

Variable shadowing happens when a new variable defined within a certain scope (like a function or block) uses the same name as a variable defined in an outer scope. The local variable then takes precedence, effectively hiding the outer-scope variable within the inner scope. In languages like Java and JavaScript, variable shadowing can inadvertently occur and lead to code readability issues or logic errors, as it becomes unclear which variable the code refers to at any given time. Although variable shadowing is allowed by language rules, it typically indicates poor coding practices, making debugging and maintenance more difficult.
[ FAQ2 ]

How to fix variable shadowing

To fix variable shadowing, avoid reusing variable names across different scopes within the same function or class. Choose unique and descriptive variable names to maintain clarity. For example, if an outer variable is userCount, use a different, more specific name like tempUserCount or currentUserCount within an inner scope. Utilize linters or IDE warnings, available in languages like Java and JavaScript, to detect shadowing early. Additionally, refactor your code by breaking large blocks into smaller functions or methods, clearly defining separate variables with distinct, scoped names to prevent accidental shadowing.
diff block
+/*
+Copyright © 2025 NAME HERE <EMAIL ADDRESS>
+*/
+package cmd
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/ammar-ahmed22/chlog/ai"
+ "github.com/spf13/cobra"
+)
+
+func printModels(provider string, models []string, envVar string) {
+ fmt.Printf("Provider: %s", provider)
+ if envVar != "" {
+ fmt.Printf(" (env var: %s)", envVar)
+ }
+ fmt.Println()
+ for i, model := range models {
+ if i == 0 {
+ fmt.Printf(" - %s (default)\n", model)
+ continue
+ }
+ fmt.Printf(" - %s\n", model)
+ }
+ fmt.Println()
+}
+
+// modelsCmd represents the models command
+var modelsCmd = &cobra.Command{
+ Use: "models",
+ Short: "List supported models and providers",
+ RunE: func(cmd *cobra.Command, args []string) error {
+ provider, err := cmd.Flags().GetString("provider")
+ if err != nil {
+ return err
+ }
+
+ if provider == "all" {
+ fmt.Println("Supported providers and models:")
+ fmt.Println()
+ for provider, model := range ai.ProvidersMap {
+ envVar := ai.ProviderEnvVarMap[provider]
+ printModels(provider, model, envVar)
+ }
Greptile
greptile
logic: Variable shadowing: loop variable 'provider' shadows the outer provider variable. Use a different name like 'p' to avoid confusion
diff block
-import { Injectable } from '@nestjs/common';
+import {
+ Injectable,
+ Logger,
+ OnApplicationBootstrap,
+ OnModuleInit,
+} from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { ConfigVariables } from 'src/engine/core-modules/twenty-config/config-variables';
import { CONFIG_VARIABLES_MASKING_CONFIG } from 'src/engine/core-modules/twenty-config/constants/config-variables-masking-config';
import { ConfigVariablesMetadataOptions } from 'src/engine/core-modules/twenty-config/decorators/config-variables-metadata.decorator';
+import { DatabaseConfigDriver } from 'src/engine/core-modules/twenty-config/drivers/database-config.driver';
+import { EnvironmentConfigDriver } from 'src/engine/core-modules/twenty-config/drivers/environment-config.driver';
import { ConfigVariablesMaskingStrategies } from 'src/engine/core-modules/twenty-config/enums/config-variables-masking-strategies.enum';
+import { InitializationState } from 'src/engine/core-modules/twenty-config/enums/initialization-state.enum';
import { configVariableMaskSensitiveData } from 'src/engine/core-modules/twenty-config/utils/config-variable-mask-sensitive-data.util';
import { TypedReflect } from 'src/utils/typed-reflect';
@Injectable()
-export class TwentyConfigService {
- constructor(private readonly configService: ConfigService) {}
+export class TwentyConfigService
+ implements OnModuleInit, OnApplicationBootstrap
+{
+ private driver: DatabaseConfigDriver | EnvironmentConfigDriver;
+ private initializationState = InitializationState.NOT_INITIALIZED;
+ private readonly isConfigVarInDbEnabled: boolean;
+ private readonly logger = new Logger(TwentyConfigService.name);
+
+ constructor(
+ private readonly configService: ConfigService,
+ private readonly databaseConfigDriver: DatabaseConfigDriver,
+ private readonly environmentConfigDriver: EnvironmentConfigDriver,
+ ) {
+ this.driver = this.environmentConfigDriver;
+
+ const configVarInDb = this.configService.get('IS_CONFIG_VAR_IN_DB_ENABLED');
+
+ this.isConfigVarInDbEnabled = configVarInDb === true;
+
+ this.logger.log(
+ `Database configuration is ${this.isConfigVarInDbEnabled ? 'enabled' : 'disabled'}`,
+ );
+ }
+
+ async onModuleInit() {
+ if (!this.isConfigVarInDbEnabled) {
+ this.logger.log(
+ 'Database configuration is disabled, using environment variables only',
+ );
+ this.initializationState = InitializationState.INITIALIZED;
+
+ return;
+ }
+
+ this.logger.log(
+ 'Database configuration is enabled, will initialize after application bootstrap',
+ );
+ }
+
+ async onApplicationBootstrap() {
+ if (!this.isConfigVarInDbEnabled) {
+ return;
+ }
+
+ try {
+ this.logger.log('Initializing database driver for configuration');
+ this.initializationState = InitializationState.INITIALIZING;
+
+ await this.databaseConfigDriver.initialize();
+
+ this.driver = this.databaseConfigDriver;
+ this.initializationState = InitializationState.INITIALIZED;
+ this.logger.log('Database driver initialized successfully');
+ this.logger.log(`Active driver: DatabaseDriver`);
+ } catch (error) {
+ this.logger.error(
+ 'Failed to initialize database driver, falling back to environment variables',
+ error,
+ );
+ this.initializationState = InitializationState.FAILED;
+
+ this.driver = this.environmentConfigDriver;
+ this.logger.log(`Active driver: EnvironmentDriver (fallback)`);
+ }
+ }
get<T extends keyof ConfigVariables>(key: T): ConfigVariables[T] {
- return this.configService.get<ConfigVariables[T]>(
- key,
- new ConfigVariables()[key],
+ const value = this.driver.get(key);
+
+ this.logger.debug(
+ `Getting value for '${key}' from ${this.driver.constructor.name}`,
+ {
+ valueType: typeof value,
+ isArray: Array.isArray(value),
+ value: typeof value === 'object' ? JSON.stringify(value) : value,
+ },
);
+
+ return value;
+ }
+
+ async update<T extends keyof ConfigVariables>(
+ key: T,
+ value: ConfigVariables[T],
+ ): Promise<void> {
+ if (!this.isConfigVarInDbEnabled) {
+ throw new Error(
+ 'Database configuration is disabled, cannot update configuration',
+ );
+ }
+
+ if (this.initializationState !== InitializationState.INITIALIZED) {
+ throw new Error(
+ 'Environment service not initialized, cannot update configuration',
+ );
+ }
+
+ const metadata =
+ TypedReflect.getMetadata('config-variables', ConfigVariables) ?? {};
+ const envMetadata = metadata[key];
+
+ if (envMetadata?.isEnvOnly) {
+ throw new Error(
+ `Cannot update environment-only variable: ${key as string}`,
+ );
+ }
+
+ if (this.driver === this.databaseConfigDriver) {
+ await this.databaseConfigDriver.update(key, value);
+ } else {
+ throw new Error(
+ 'Database driver not active, cannot update configuration',
+ );
+ }
+ }
+
+ getMetadata(
+ key: keyof ConfigVariables,
+ ): ConfigVariablesMetadataOptions | undefined {
+ const metadata =
+ TypedReflect.getMetadata('config-variables', ConfigVariables) ?? {};
+
+ return metadata[key];
}
getAll(): Record<
string,
{
value: ConfigVariables[keyof ConfigVariables];
metadata: ConfigVariablesMetadataOptions;
+ source: string;
}
> {
const result: Record<
string,
{
value: ConfigVariables[keyof ConfigVariables];
metadata: ConfigVariablesMetadataOptions;
+ source: string;
}
> = {};
- const configVars = new ConfigVariables();
+ const envVars = new ConfigVariables();
const metadata =
TypedReflect.getMetadata('config-variables', ConfigVariables) ?? {};
+ const isUsingDatabaseDriver =
+ this.driver === this.databaseConfigDriver &&
+ this.isConfigVarInDbEnabled &&
+ this.initializationState === InitializationState.INITIALIZED;
+
Object.entries(metadata).forEach(([key, envMetadata]) => {
- let value =
- this.configService.get(key) ??
- configVars[key as keyof ConfigVariables] ??
- '';
+ let value = this.get(key as keyof ConfigVariables) ?? '';
+ let source = 'ENVIRONMENT';
+
+ if (isUsingDatabaseDriver && !envMetadata.isEnvOnly) {
+ const value = this.get(key as keyof ConfigVariables);
+
Greptile
greptile
logic: Variable shadowing issue - the inner `value` shadows the outer one, making the condition check incorrect. This will always use the same value for comparison.
suggested fix
if (isUsingDatabaseDriver && !envMetadata.isEnvOnly) {
+ const dbValue = this.get(key as keyof ConfigVariables);