laurent22/joplin · error · Error

Failed to extract a valid commit hash. Ensure that git is pr

Error message

Failed to extract a valid commit hash. Ensure that git is properly initialized and you have made at least one local commit (git commit) before publishing.

What it means

Thrown by the plugin-publish verifyGitState step when the local commit hash from `git rev-parse HEAD` is not exactly 40 characters. A valid git SHA-1 hash is always 40 hex chars; a different length indicates git is not initialized properly, has no commits, or the command output was anomalous (e.g. a prefixed 'fatal:' message that bypassed the earlier runGit catch, or stdout trimming produced empty/garbage).

Source

Thrown at packages/generator-joplin/generators/app/templates/script/publish/steps/verifyGitState.ts:35

			}
			throw error;
		}
	};

	// Checks if the current folder is a git repository or not
	await runGit('git rev-parse --is-inside-work-tree', 'The current directory is not a git repository or git is not installed.');

	// Checks if there is any uncommitted changes
	const status = await runGit('git status --porcelain', 'Failed to check git status. Ensure git is installed and configured.');
	if (status !== '') {
		throw new Error('You have uncommitted changes. Please commit or stash them before publishing.');
	}
	logger.success('Working tree is clean.');

	// Gets the current latest local commit hash
	const commitHash = await runGit('git rev-parse HEAD', 'Could not get commit hash. Ensure you are in a valid Git repository with at least one commit.');
	if (commitHash.length !== 40) {
		throw new Error('Failed to extract a valid commit hash. Ensure that git is properly initialized and you have made at least one local commit (git commit) before publishing.');
	}
	logger.success(`Commit hash extracted: ${commitHash}`);

	// check if the local project is linked to github
	await runGit('git remote get-url origin', 'No remote named \'origin\' found. Make sure your plugin repository is hosted on GitHub.');

	const currentBranch = await runGit('git rev-parse --abbrev-ref HEAD', 'Failed to retrieve current branch name. Ensure git is configured correctly.');
	if (currentBranch === 'HEAD') {
		throw new Error('You are in a detached HEAD state. Checkout a branch (e.g. git checkout main) and push before publishing.');
	}

	const remoteHeadLine = await runGit(`git ls-remote origin ${currentBranch}`, 'Could not retrieve remote HEAD. Make sure you have pushed your changes and have an internet connection.');
	if (!remoteHeadLine) {
		throw new Error('Remote HEAD is empty. Make sure you have pushed your changes.');
	}

	const parts = remoteHeadLine.split('\n')[0].split(/\s+/);
	if (parts.length < 2) {

View on GitHub (pinned to 2654b33620)

Solutions

  1. Make at least one commit before publishing: git add -A && git commit -m 'initial commit'.
  2. Confirm git is installed and on PATH: git --version.
  3. Verify HEAD has a commit: git rev-parse HEAD should print 40 hex chars.
  4. If in CI, ensure the checkout action fetches full history (fetch-depth: 0) and that a commit exists.

Example fix

# before — publish in a repo with no commits
npm run publish
# after
 git add -A && git commit -m 'initial commit'
 npm run publish
Defensive patterns

Strategy: validation

Validate before calling

const { execSync } = require('child_process');
const hash = execSync('git rev-parse HEAD', { encoding: 'utf8' }).trim();
if (!/^[0-9a-f]{40}$/.test(hash)) {
  throw new Error('No valid commit hash. Run: git commit');
}

Type guard

function isValidCommitHash(h) { return /^[0-9a-f]{40}$/.test(h); }

Prevention

When it happens

Trigger: git rev-parse HEAD returned empty (no commits yet — repo just init'd); git is not installed so the earlier runGit already should have thrown but a partial install returned garbage; the hash got truncated by a proxy/wrapper; HEAD points to an unborn branch.

Common situations: Running `npm run publish` in a freshly `git init`'d plugin repo with zero commits; git not on PATH in the publish environment (CI) producing odd output; a shallow clone edge case; the working dir is not actually a git repo but a tool emulated git.

Related errors


AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12). Data as JSON: /api/errors/1ffab74922b48258. Report an issue: GitHub.