Skip to content

Conversation

@hongkongkiwi
Copy link

@hongkongkiwi hongkongkiwi commented Jan 25, 2026

Summary

Fixed issues identified in the comprehensive code review report across error handling, memory leaks, type safety, edge cases, security, and code quality.

Memory Leaks & Resource Cleanup

  • CacheManager: Added exitHandlerRegistered guard flag to prevent duplicate exit handlers
  • CacheManager: Fixed evictOldest() edge case with empty cache
  • TemplateServerManager: Added exitHandlerRegistered guard flag to prevent duplicate exit handlers
  • TemplateServerManager: Replaced unsafe ! non-null assertion with proper null check
  • FileStorageService: Already has public shutdown() method (no change needed)
  • StreamableSessionRepository: Already has stopPeriodicFlush() method (no change needed)

Error Handling

  • mcpLoadingManager: Background retry wrapped in try/catch
  • sseRoutes: Heartbeat errors logged at debug level, transport cleanup on error

Type Safety

  • clientInstancePool: Removed unsafe ! non-null assertions, using nullish coalescing (??) instead
  • FileStorageService JSON.parse: Has proper try/catch error handling (no change needed)

Edge Cases

  • presetManager: Added minimum length validation (at least 1 character) for preset names
  • loadingStateTracker: Fixed potential division by zero in averageLoadTime calculation

Code Quality - Refactoring

  • connectionHelper: Extracted duplicate timeout pattern into reusable createTimeout() helper function
  • notificationManager: Unified duplicate sendXxxListChangedNotification methods with single sendListChangedNotification
  • constants/timeouts: Added TEMPLATE_CLEANUP_INTERVAL (30s) and TEMPLATE_IDLE_TIMEOUT (10min) constants
  • templateServerManager: Replaced inline magic numbers with TIMEOUTS constants
  • filterCache: Use TIMEOUTS.CLEANUP_INTERVAL instead of inline magic number
  • pidFileManager: Refactored duplicate signal handler registrations into a loop

Tests Added

  • src/commands/mcp/utils/connectionHelper.test.ts - Tests for createTimeout helper

Files Changed

File Changes
src/domains/registry/cacheManager.ts +14 lines
src/core/server/templateServerManager.ts +18 lines
src/core/loading/loadingStateTracker.ts +4 lines
src/commands/mcp/utils/connectionHelper.ts +11 lines
src/commands/mcp/utils/connectionHelper.test.ts New file
src/constants/timeouts.ts +4 lines
src/core/notifications/notificationManager.ts Refactored
src/core/server/clientInstancePool.ts Refactored
src/core/filtering/filterCache.ts -2 lines
src/core/server/pidFileManager.ts -6 lines

Test Results

  • 150 test files passed
  • 2924 tests passed

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced centralized timeout configuration for consistent behavior across the application.
  • Bug Fixes

    • Preset names now require a minimum length of 1 character.
    • Improved error handling during heartbeat failures in server transport with graceful cleanup.
    • Enhanced resource cleanup and graceful shutdown during process exit.
  • Tests

    • Added comprehensive tests for timeout functionality.

✏️ Tip: You can customize this high-level summary in your review settings.

hongkongkiwi and others added 4 commits January 25, 2026 20:20
- Add destroy() method with process exit handler to CacheManager
- Fix TemplateServerManager.cleanup() to clear session maps
- Add process signal handlers to FileStorageService
- Prevent multiple process handlers in pidFileManager with guard flags
- Wrap background retry in try/catch in mcpLoadingManager
- Add debug logging and transport cleanup to sseRoutes
- Remove unsafe non-null assertions in clientInstancePool
- Add minimum length validation for preset names
- Create centralized timeout constants file
- Create Shutdownable interface for graceful shutdown

Co-Authored-By: Claude <[email protected]>
- CacheManager: Add guard flag to prevent duplicate exit handler registration
- CacheManager: Fix evictOldest() edge case with empty cache
- TemplateServerManager: Add guard flag to prevent duplicate exit handler
- TemplateServerManager: Replace unsafe non-null assertion with proper null check
- LoadingStateTracker: Fix potential division by zero in averageLoadTime calculation

Co-Authored-By: Claude <[email protected]>
- Extract duplicate timeout pattern into reusable createTimeout() function
- Replace 4 inline timeout patterns with the helper function
- Add tests for the createTimeout helper

Co-Authored-By: Claude <[email protected]>
- Extract TEMPLATE_CLEANUP_INTERVAL and TEMPLATE_IDLE_TIMEOUT constants
- Replace inline magic numbers in templateServerManager with TIMEOUTS constants
- Unify duplicate sendXxxListChangedNotification methods with single sendListChangedNotification

Co-Authored-By: Claude <[email protected]>
- filterCache.ts: Use TIMEOUTS.CLEANUP_INTERVAL instead of inline magic number
- pidFileManager.ts: Refactor duplicate signal handler registrations into a loop

Co-Authored-By: Claude <[email protected]>
@xizhibei
Copy link
Contributor

Thanks again for your contribution. This PR looks solid and addresses several issues. However, please allow me some time to review it thoroughly.

@xizhibei xizhibei added the enhancement New feature or request label Jan 26, 2026
@hongkongkiwi
Copy link
Author

Sure! Highly recommend to enable coderabbit, it's free for opensource projects and provides solid feedback for PRs, useful for contributers :)

@xizhibei
Copy link
Contributor

Good idea, setting up right now, and could you just take a look about the failing CI test ?

@xizhibei
Copy link
Contributor

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Jan 27, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai
Copy link

coderabbitai bot commented Jan 27, 2026

📝 Walkthrough

Walkthrough

This pull request introduces centralized timeout configuration, adds graceful shutdown mechanisms with process exit handlers and handler registration guards across multiple services, and improves error handling and defensive programming throughout the application. A new Shutdownable interface is introduced to standardize shutdown implementations.

Changes

Cohort / File(s) Summary
Timeout Configuration
src/constants/timeouts.ts
New module exporting immutable TIMEOUTS object with predefined values for SSE heartbeat, idle timeouts, cleanup intervals, file storage cleanup, and template-related operations. Also defines TimeoutValue type.
Timeout Integration
src/core/filtering/filterCache.ts, src/core/server/templateServerManager.ts
Replaced hardcoded timeout values with TIMEOUTS constants. TemplateServerManager also updates default parameter in getIdleTemplateInstances and adds local session map initialization pattern.
Connection Utilities
src/commands/mcp/utils/connectionHelper.ts, src/commands/mcp/utils/connectionHelper.test.ts
Adds new createTimeout(ms, message) utility function for standardized timeout promises. Refactors Promise.race calls to use this helper. Test suite validates function rejection and timing behavior.
Handler Registration Guards
src/core/server/pidFileManager.ts, src/core/server/pidFileManager.test.ts
Introduces internal flags (cleanupRegistered, signalHandlersRegistered) to prevent multiple registrations. Exposes _resetHandlerFlags() testing helper. Refactors signal registration to loop over signals array.
Process Exit Handlers
src/auth/storage/fileStorageService.ts, src/core/server/templateServerManager.ts, src/domains/registry/cacheManager.ts
Adds process 'exit' or 'beforeExit' listeners for graceful shutdown. TemplateServerManager adds exitHandlerRegistered guard. CacheManager validates regex input and caps eviction bounds safely.
Notification System
src/core/notifications/notificationManager.ts
Refactors three private list-changed notification methods to route through new sendListChangedNotification helper, consolidating payload construction.
Defensive Programming
src/core/server/clientInstancePool.ts, src/core/loading/loadingStateTracker.ts, src/domains/preset/manager/presetManager.ts
Replaces logical OR with nullish coalescing for safer defaulting. Adds safety checks around map retrievals. Refactors duration calculation in loading tracker. Adds minimum length validation (1 character) for preset names.
Error Handling & Logging
src/core/loading/mcpLoadingManager.ts, src/transport/http/routes/sseRoutes.ts
Wraps background retry with try/catch to log errors without breaking timer. Improves SSE transport cleanup with debugIf logging and optional chaining; adds error cleanup path calling transport.close().
Interface Definition
src/interfaces/shutdownable.ts
New interface defining shutdown(): Promise\<void\>

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 Timeouts now organized, handlers stand guard,
Exit paths cleaned with a touch of retard,
Safer defaults flow where errors once crashed,
This refactor's robust—a job well-hashed! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: resolve memory leaks, error handling, and edge cases' accurately summarizes the main objectives of the changeset, covering the three primary themes addressed across all files.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
src/domains/registry/cacheManager.ts (1)

168-179: Exit handler registration logic is misplaced.

Registering the process exit handler inside destroy() creates confusing behavior:

  1. On first destroy() call, the timer is cleared, then the exit handler is registered
  2. On process exit, destroy() is called again (though harmless due to the guard)

The exit handler should be registered in the constructor to ensure cleanup happens on process exit even if destroy() was never explicitly called.

🐛 Suggested fix: move exit handler to constructor
   constructor(options: Partial<CacheOptions> = {}) {
     this.options = {
       defaultTtl: options.defaultTtl || 300,
       maxSize: options.maxSize || 1000,
       cleanupInterval: options.cleanupInterval || 60000,
     };

     this.startCleanupTimer();
+
+    // Register process exit handler for graceful shutdown (only once)
+    if (typeof process !== 'undefined' && !this.exitHandlerRegistered) {
+      this.exitHandlerRegistered = true;
+      process.on('exit', () => this.destroy());
+    }
   }

   // ...

   destroy(): void {
     if (this.cleanupTimer) {
       clearInterval(this.cleanupTimer);
       this.cleanupTimer = undefined;
     }
-
-    // Register process exit handler for graceful shutdown (only once)
-    if (typeof process !== 'undefined' && !this.exitHandlerRegistered) {
-      this.exitHandlerRegistered = true;
-      process.on('exit', () => this.destroy());
-    }
   }
src/core/server/templateServerManager.ts (1)

66-69: Fix undefined variable cleanupInterval (pipeline failure).

The variable cleanupInterval is not defined. This was likely the old hardcoded constant that was replaced. The debug log should reference TIMEOUTS.TEMPLATE_CLEANUP_INTERVAL instead.

🐛 Proposed fix
     debugIf(() => ({
       message: 'TemplateServerManager cleanup timer started',
-      meta: { interval: cleanupInterval },
+      meta: { interval: TIMEOUTS.TEMPLATE_CLEANUP_INTERVAL },
     }));
src/core/server/clientInstancePool.ts (1)

504-524: Pass template-level maxInstances to checkInstanceLimits() for proper enforcement.

getTemplateSettings() computes templateConfig.template.maxInstances, but checkInstanceLimits() only checks pool-level this.options.maxInstances, so template-specific limits are never enforced. The template-level setting is computed at line 134 and available, but not passed to the limit check at line 153.

🛠️ Suggested wiring
-  private checkInstanceLimits(templateName: string): void {
-    const maxInstances = this.options.maxInstances ?? DEFAULT_POOL_OPTIONS.maxInstances;
+  private checkInstanceLimits(templateName: string, maxInstances?: number): void {
+    const effectiveMaxInstances =
+      maxInstances ?? this.options.maxInstances ?? DEFAULT_POOL_OPTIONS.maxInstances;
     // Check per-template limit
-    if (maxInstances > 0) {
+    if (effectiveMaxInstances > 0) {
       const templateInstances = this.getTemplateInstances(templateName);
       const activeCount = templateInstances.filter((instance) => instance.status !== 'terminating').length;
 
-      if (activeCount >= maxInstances) {
-        throw new Error(`Maximum instances (${maxInstances}) reached for template '${templateName}'`);
+      if (activeCount >= effectiveMaxInstances) {
+        throw new Error(
+          `Maximum instances (${effectiveMaxInstances}) reached for template '${templateName}'`,
+        );
       }
     }
-    this.checkInstanceLimits(templateName);
+    this.checkInstanceLimits(templateName, templateSettings.maxInstances);
🤖 Fix all issues with AI agents
In `@src/core/loading/mcpLoadingManager.ts`:
- Around line 303-308: The interval handler for backgroundRetryTimer currently
calls the async method performBackgroundRetry() without awaiting it, so
rejections escape the try/catch; change the setInterval callback to be async and
await this.performBackgroundRetry() inside the try block (i.e., make the
anonymous function async and use await) so any thrown/rejected errors are caught
by the existing catch that logs via logger.error; keep the same logger usage and
ensure the surrounding reference is to this.performBackgroundRetry().

In `@src/core/server/templateServerManager.ts`:
- Around line 443-444: The exit handler registration currently placed inside
cleanup() must be moved into the class constructor so the handler is always
registered on process start; locate references to exitHandlerRegistered and the
code that attaches process 'exit'/'SIGINT' handlers (also present around lines
464-468) and move that registration into the constructor, removing it from
cleanup(); additionally add a one-time guard inside cleanup() (e.g., a
cleanupRan boolean or reuse exitHandlerRegistered semantics to track execution)
so cleanup() becomes a no-op on subsequent calls to avoid duplicate execution
when the process exit handler invokes it.

In `@src/domains/preset/manager/presetManager.ts`:
- Around line 472-479: The empty-string branch is unreachable because the
initial check uses "!name", which also matches '' — change the presence/type
check to only reject null/undefined (e.g., use name == null || typeof name !==
'string') so the subsequent name.length < 1 branch can run and produce the
distinct message; update the validation logic around the name variable in
presetManager.ts (the block containing the checks for name, name.length, and the
/^[a-zA-Z0-9_-]+$/ test) accordingly.
🧹 Nitpick comments (5)
src/core/notifications/notificationManager.ts (1)

204-226: Consider typing the method argument as a string literal union
This avoids accidental typos in notification method names while keeping the helper.

♻️ Suggested tweak
-  private sendListChangedNotification(type: 'tools' | 'resources' | 'prompts', method: string): void {
+  private sendListChangedNotification(
+    type: 'tools' | 'resources' | 'prompts',
+    method:
+      | 'notifications/tools/list_changed'
+      | 'notifications/resources/list_changed'
+      | 'notifications/prompts/list_changed',
+  ): void {
     this.sendNotification(type, { method, params: {} });
   }
src/core/loading/loadingStateTracker.ts (1)

247-251: LGTM! The division-by-zero fix and logic correction are sound.

The change correctly guards against division by zero and also fixes a subtle bug where the average was previously computed using completedStates.length as the divisor—even when some of those states lacked a defined duration, which would skew the average downward.

One minor nitpick: the variable durations holds ServerLoadingInfo[] objects rather than actual duration numbers. Consider renaming to statesWithDuration for clarity, or extracting the durations directly:

const durations = completedStates
  .map((s) => s.duration)
  .filter((d): d is number => d !== undefined);
const averageLoadTime =
  durations.length > 0
    ? durations.reduce((sum, d) => sum + d, 0) / durations.length
    : undefined;

This is optional and doesn't affect correctness.

,

src/auth/storage/fileStorageService.ts (1)

344-350: Missing exit-handler guard flag, unlike other managers in this PR.

Each FileStorageService instance registers a new beforeExit handler without deduplication. If multiple instances are created (e.g., for different storage subdirectories), handlers accumulate. The PR description mentions that CacheManager and TemplateServerManager received guard flags to prevent this—this file should follow the same pattern for consistency.

♻️ Suggested fix: Add a static guard flag
 export class FileStorageService {
   private storageDir: string;
   private cleanupInterval: ReturnType<typeof setInterval> | null = null;
+  private static exitHandlerRegistered = false;
+  private static instances: Set<FileStorageService> = new Set();

   // ... existing code ...

   private startPeriodicCleanup(): void {
     // Clean up expired data every 5 minutes
     this.cleanupInterval = setInterval(
       () => {
         this.cleanupExpiredData();
       },
       5 * 60 * 1000,
     );

+    FileStorageService.instances.add(this);
+
     // Ensure cleanup on process exit
-    if (typeof process !== 'undefined') {
+    if (typeof process !== 'undefined' && !FileStorageService.exitHandlerRegistered) {
+      FileStorageService.exitHandlerRegistered = true;
       process.on('beforeExit', () => {
-        this.shutdown();
+        for (const instance of FileStorageService.instances) {
+          instance.shutdown();
+        }
       });
     }
   }

   shutdown(): void {
     if (this.cleanupInterval) {
       clearInterval(this.cleanupInterval);
       this.cleanupInterval = null;
       logger.info('FileStorageService cleanup interval stopped');
     }
+    FileStorageService.instances.delete(this);
   }
src/commands/mcp/utils/connectionHelper.ts (1)

57-61: Consider using createTimeout here for consistency.

The new createTimeout helper is used elsewhere in this file (lines 139, 154, 169, 201), but connectToServers still creates a timeout promise inline. Consider refactoring for consistency.

♻️ Suggested refactor
-        // Create a timeout promise
-        const timeoutPromise = new Promise<never>((_, reject) => {
-          setTimeout(() => {
-            reject(new Error(`Connection timeout after ${timeoutMs}ms`));
-          }, timeoutMs);
-        });
+        // Create a timeout promise
+        const timeoutPromise = createTimeout(timeoutMs, `Connection timeout after ${timeoutMs}ms`);
src/core/server/pidFileManager.test.ts (1)

379-382: Make handler-flag resets suite-wide to avoid order dependence.

The global flags persist across tests; resetting only in this test can cause false positives if another test already set the flags. Consider resetting in a shared beforeEach/afterEach for the describe block (or top-level) instead.

🔧 Suggested change
 describe('pidFileManager', () => {
+  beforeEach(() => {
+    _resetHandlerFlags();
+  });

Comment on lines 303 to +308
this.backgroundRetryTimer = setInterval(() => {
this.performBackgroundRetry();
try {
this.performBackgroundRetry();
} catch (error) {
logger.error('Error during background retry:', error);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, let's check if the file exists and examine the relevant lines
cat -n src/core/loading/mcpLoadingManager.ts | sed -n '295,320p'

Repository: 1mcp-app/agent

Length of output: 986


🏁 Script executed:

# Also search for the performBackgroundRetry method definition
rg "performBackgroundRetry\s*\(" src/core/loading/mcpLoadingManager.ts -A 3

Repository: 1mcp-app/agent

Length of output: 374


Async errors still escape the try/catch in the interval handler.

performBackgroundRetry() is declared as async and returns Promise<void> (line 317). Without await, the try/catch block cannot capture rejections from the promise, leaving unhandled promise rejections possible. Add async to the callback and await the call to properly handle errors.

✅ Suggested fix
-    this.backgroundRetryTimer = setInterval(() => {
+    this.backgroundRetryTimer = setInterval(async () => {
       try {
-        this.performBackgroundRetry();
+        await this.performBackgroundRetry();
       } catch (error) {
         logger.error('Error during background retry:', error);
       }
     }, this.config.backgroundRetryIntervalMs);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.backgroundRetryTimer = setInterval(() => {
this.performBackgroundRetry();
try {
this.performBackgroundRetry();
} catch (error) {
logger.error('Error during background retry:', error);
}
this.backgroundRetryTimer = setInterval(async () => {
try {
await this.performBackgroundRetry();
} catch (error) {
logger.error('Error during background retry:', error);
}
}, this.config.backgroundRetryIntervalMs);
🤖 Prompt for AI Agents
In `@src/core/loading/mcpLoadingManager.ts` around lines 303 - 308, The interval
handler for backgroundRetryTimer currently calls the async method
performBackgroundRetry() without awaiting it, so rejections escape the
try/catch; change the setInterval callback to be async and await
this.performBackgroundRetry() inside the try block (i.e., make the anonymous
function async and use await) so any thrown/rejected errors are caught by the
existing catch that logs via logger.error; keep the same logger usage and ensure
the surrounding reference is to this.performBackgroundRetry().

Comment on lines +443 to +444
private exitHandlerRegistered = false;

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Exit handler registration is misplaced inside cleanup().

The exit handler is registered inside cleanup(), which has two problems:

  1. Handler may never be registered: If cleanup() isn't called before process exit, the handler won't exist.
  2. Duplicate cleanup execution: If cleanup() is called manually, then on process exit it runs again (the guard only prevents re-registration, not re-execution).

The exit handler should be registered in the constructor to ensure it's always active.

♻️ Proposed fix - move registration to constructor
   constructor() {
     // Initialize the client instance pool
     this.clientInstancePool = new ClientInstancePool({
       maxInstances: 50, // Configurable limit
       idleTimeout: TIMEOUTS.IDLE_TIMEOUT,
       cleanupInterval: TIMEOUTS.TEMPLATE_CLEANUP_INTERVAL,
     });

     // Start cleanup timer for idle template instances
     this.startCleanupTimer();
+
+    // Register process exit handler for graceful shutdown (only once)
+    if (typeof process !== 'undefined' && !this.exitHandlerRegistered) {
+      this.exitHandlerRegistered = true;
+      process.on('exit', () => this.cleanup());
+    }
   }

And remove from cleanup():

   public cleanup(): void {
     // Clean up cleanup timer
     if (this.cleanupTimer) {
       clearInterval(this.cleanupTimer);
       this.cleanupTimer = undefined;
     }

     // Clear session-to-rendered-hash mapping
     this.sessionToRenderedHash.clear();

     // Clear template session map
     this.templateSessionMap?.clear();

     // Clean up the client instance pool
     this.clientInstancePool?.cleanupIdleInstances();
-
-    // Register process exit handler for graceful shutdown (only once)
-    if (typeof process !== 'undefined' && !this.exitHandlerRegistered) {
-      this.exitHandlerRegistered = true;
-      process.on('exit', () => this.cleanup());
-    }
   }

Also applies to: 464-468

🤖 Prompt for AI Agents
In `@src/core/server/templateServerManager.ts` around lines 443 - 444, The exit
handler registration currently placed inside cleanup() must be moved into the
class constructor so the handler is always registered on process start; locate
references to exitHandlerRegistered and the code that attaches process
'exit'/'SIGINT' handlers (also present around lines 464-468) and move that
registration into the constructor, removing it from cleanup(); additionally add
a one-time guard inside cleanup() (e.g., a cleanupRan boolean or reuse
exitHandlerRegistered semantics to track execution) so cleanup() becomes a no-op
on subsequent calls to avoid duplicate execution when the process exit handler
invokes it.

Comment on lines 472 to 479
// Validate name
if (!name || typeof name !== 'string') {
errors.push('Preset name is required and must be a string');
} else if (name.length < 1) {
errors.push('Preset name must be at least 1 character');
} else if (name.length > 50) {
errors.push('Preset name must be 50 characters or less');
} else if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Empty-string check is unreachable

!name already catches '', so the new name.length < 1 branch never runs. If you want a distinct message for empty strings, split the checks.

Suggested fix
-    if (!name || typeof name !== 'string') {
+    if (typeof name !== 'string') {
       errors.push('Preset name is required and must be a string');
-    } else if (name.length < 1) {
+    } else if (name.length === 0) {
       errors.push('Preset name must be at least 1 character');
     } else if (name.length > 50) {
       errors.push('Preset name must be 50 characters or less');
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Validate name
if (!name || typeof name !== 'string') {
errors.push('Preset name is required and must be a string');
} else if (name.length < 1) {
errors.push('Preset name must be at least 1 character');
} else if (name.length > 50) {
errors.push('Preset name must be 50 characters or less');
} else if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
// Validate name
if (typeof name !== 'string') {
errors.push('Preset name is required and must be a string');
} else if (name.length === 0) {
errors.push('Preset name must be at least 1 character');
} else if (name.length > 50) {
errors.push('Preset name must be 50 characters or less');
} else if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
🤖 Prompt for AI Agents
In `@src/domains/preset/manager/presetManager.ts` around lines 472 - 479, The
empty-string branch is unreachable because the initial check uses "!name", which
also matches '' — change the presence/type check to only reject null/undefined
(e.g., use name == null || typeof name !== 'string') so the subsequent
name.length < 1 branch can run and produce the distinct message; update the
validation logic around the name variable in presetManager.ts (the block
containing the checks for name, name.length, and the /^[a-zA-Z0-9_-]+$/ test)
accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants