Skip to content

Fix npx-thunderid failing to start when install directory exists but pack contents are deleted#3075

Open
rajithacharith wants to merge 1 commit into
thunder-id:mainfrom
rajithacharith:npx-tool
Open

Fix npx-thunderid failing to start when install directory exists but pack contents are deleted#3075
rajithacharith wants to merge 1 commit into
thunder-id:mainfrom
rajithacharith:npx-tool

Conversation

@rajithacharith
Copy link
Copy Markdown
Contributor

@rajithacharith rajithacharith commented May 29, 2026

Purpose

When a user manually deletes the downloaded Thunder pack contents but leaves the install directory on disk, npx thunderid fails to start with:

Failed to start ThunderID: Thunder installation not found in /Users/<user>/<version>

The alreadyInstalled check used fs.existsSync on the install path, which only confirms the directory exists — not that the Thunder files inside are intact.

Approach

Replace the shallow fs.existsSync(versionState.installPath) check with findThunderRoot(versionState.installPath) !== null in tools/npx-thunderid/src/index.ts. findThunderRoot looks for setup.sh (or setup.ps1 on Windows) inside the directory, which is the true signal that the installation is usable. A missing setup script now correctly marks the install as absent and triggers a fresh download.

Related Issues

Related PRs

  • N/A

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
    • Ran Vale and fixed all errors and warnings
  • Tests provided. (Add links if there are any)
    • Unit Tests
    • Integration Tests
  • Breaking changes. (Fill if applicable)
    • Breaking changes section filled.
    • breaking change label added.

Security checks

  • Followed secure coding standards in WSO2 Secure Coding Guidelines
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.

Summary by CodeRabbit

  • Bug Fixes

    • Improved CLI detection of existing Thunder installations to more reliably identify valid install directories and avoid false positives, reducing unnecessary re-installs or prompts.
  • Chores

    • Minor CLI cleanup to streamline detection code and reduce redundant checks.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a2ae2cd4-6da2-4614-9318-7f11993e6b75

📥 Commits

Reviewing files that changed from the base of the PR and between c01d6e6 and 570d91a.

📒 Files selected for processing (1)
  • tools/npx-thunderid/src/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • tools/npx-thunderid/src/index.ts

📝 Walkthrough

Walkthrough

The PR updates tools/npx-thunderid/src/index.ts to import findThunderRoot and use it to validate that the stored install path contains a Thunder root, replacing the prior directory-exists check.

Changes

Installation Detection Validation

Layer / File(s) Summary
Thunder installation file verification
tools/npx-thunderid/src/index.ts
Import findThunderRoot and replace the shallow fs.existsSync(versionState.installPath) check with Boolean(versionState?.installPath && findThunderRoot(versionState.installPath) !== null) to detect missing Thunder files inside the install directory.

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely describes the main bug fix: detecting and handling incomplete Thunder installations when the directory exists but contents are deleted.
Description check ✅ Passed The description includes Purpose and Approach sections with clear problem explanation and solution details. Checklist items remain unchecked as expected for an in-progress PR, but all required template sections are present.
Linked Issues check ✅ Passed The code changes directly implement the suggested fix from issue #3074 by replacing fs.existsSync() with findThunderRoot() validation to detect incomplete installations.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing the alreadyInstalled check in index.ts as specified in issue #3074; no unrelated modifications are present.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

tools/npx-thunderid/src/index.ts

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
Contributor

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tools/npx-thunderid/src/index.ts`:
- Line 70: The current alreadyInstalled check calls
findThunderRoot(versionState.installPath) which can throw ENOENT because
findThunderRoot -> findSetupScript calls fs.readdirSync on a missing path;
update either findSetupScript or findThunderRoot to guard filesystem access with
a try/catch or explicit fs.existsSync check before calling fs.readdirSync, and
return null on failure, or alternatively add an existence guard before invoking
findThunderRoot in the alreadyInstalled computation (referencing
alreadyInstalled, versionState.installPath, findThunderRoot, findSetupScript) so
a deleted install directory yields null instead of throwing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1063dc87-d45d-4b50-87b6-1a296e5469c6

📥 Commits

Reviewing files that changed from the base of the PR and between 50e0e55 and c01d6e6.

📒 Files selected for processing (1)
  • tools/npx-thunderid/src/index.ts

const state = readState();
const versionState = state.installs[VERSION];
const alreadyInstalled = Boolean(versionState?.installPath && fs.existsSync(versionState.installPath));
const alreadyInstalled = Boolean(versionState?.installPath && findThunderRoot(versionState.installPath) !== null);
Copy link
Copy Markdown
Contributor

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:

#!/bin/bash
# Locate setup.ts and inspect findThunderRoot: confirm it's exported and guards missing paths.
fd 'setup.ts' --type f

echo "=== findThunderRoot (function-declaration form) ==="
ast-grep --pattern 'export function findThunderRoot($$$) { $$$ }'

echo "=== findThunderRoot (arrow form) ==="
ast-grep --pattern 'export const findThunderRoot = ($$$) => { $$$ }'

echo "=== Context: implementation + fs calls used inside ==="
rg -nP --type=ts -C10 'function findThunderRoot|findThunderRoot\s*='

Repository: thunder-id/thunderid

Length of output: 1891


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== tools/npx-thunderid/src/index.ts around line 70 ==="
nl -ba tools/npx-thunderid/src/index.ts | sed -n '50,100p'

echo "=== tools/npx-thunderid/src/index.ts around main() and its invocation ==="
nl -ba tools/npx-thunderid/src/index.ts | sed -n '140,210p'

echo "=== tools/npx-thunderid/src/setup.ts around findSetupScript + findThunderRoot ==="
nl -ba tools/npx-thunderid/src/setup.ts | sed -n '1,120p'

echo "=== All references to findThunderRoot in tools/npx-thunderid/src ==="
rg -n "findThunderRoot\(" tools/npx-thunderid/src

Repository: thunder-id/thunderid

Length of output: 181


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== tools/npx-thunderid/src/index.ts around line 70 ==="
cat -n tools/npx-thunderid/src/index.ts | sed -n '60,90p'

echo "=== tools/npx-thunderid/src/index.ts around main() and its invocation ==="
cat -n tools/npx-thunderid/src/index.ts | sed -n '150,220p'

echo "=== tools/npx-thunderid/src/setup.ts around findSetupScript + findThunderRoot ==="
cat -n tools/npx-thunderid/src/setup.ts | sed -n '1,140p'

echo "=== All references to findThunderRoot in tools/npx-thunderid/src ==="
rg -n "findThunderRoot\(" tools/npx-thunderid/src

Repository: thunder-id/thunderid

Length of output: 6545


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== tools/npx-thunderid/src/index.ts beginning (main / top-level error handling) ==="
cat -n tools/npx-thunderid/src/index.ts | sed -n '1,120p'

echo "=== tools/npx-thunderid/src/index.ts around alreadyInstalled usage ==="
cat -n tools/npx-thunderid/src/index.ts | sed -n '90,170p'

Repository: thunder-id/thunderid

Length of output: 7993


Fix ENOENT risk in alreadyInstalled check (findThunderRoot can throw).

tools/npx-thunderid/src/index.ts computes alreadyInstalled at line 70 by calling findThunderRoot(versionState.installPath) outside any try/catch. But findThunderRootfindSetupScript calls fs.readdirSync(installPath) without guarding that installPath exists, so deleting the whole install directory will throw (ENOENT) instead of returning null, preventing the intended graceful re-download. Add an existence guard/try-catch inside findSetupScript/findThunderRoot (or check fs.existsSync(versionState.installPath) before calling findThunderRoot).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tools/npx-thunderid/src/index.ts` at line 70, The current alreadyInstalled
check calls findThunderRoot(versionState.installPath) which can throw ENOENT
because findThunderRoot -> findSetupScript calls fs.readdirSync on a missing
path; update either findSetupScript or findThunderRoot to guard filesystem
access with a try/catch or explicit fs.existsSync check before calling
fs.readdirSync, and return null on failure, or alternatively add an existence
guard before invoking findThunderRoot in the alreadyInstalled computation
(referencing alreadyInstalled, versionState.installPath, findThunderRoot,
findSetupScript) so a deleted install directory yields null instead of throwing.

brionmario
brionmario previously approved these changes May 29, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 29, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

npx-thunderid: fails to start when install directory exists but Thunder pack contents are deleted

2 participants