affaan-m/ECC · error · Error

invalid repository

Error message

invalid repository

What it means

announcementKey composes a stable 'owner/repo:discussion:<id>' key from a repository string and discussion id. It validates the repository against /^[^/\s]+\/[^/\s]+$/ (exactly one slash, no whitespace) and throws 'invalid repository' when the value is missing, malformed, or contains spaces. This prevents downstream keys and footer references from being ambiguous.

Solutions

  1. Pass the repository as 'owner/repo' (e.g. 'affaan-m/ECC'), sourced from the GITHUB_REPOSITORY env var or an explicit config field.
  2. If you have a URL, normalize it first: new URL(u).pathname.replace(/^\//,'').replace(/\.git$/,'').
  3. Log or validate the config object before calling announcementKey so an undefined repository fails fast with a clear message.
  4. Trim whitespace on the input before constructing the object.

Example fix

// before
const key = announcementKey({ repository: 'https://github.com/affaan-m/ECC', discussionId });
// after
const repo = (process.env.GITHUB_REPOSITORY || 'affaan-m/ECC').trim();
const key = announcementKey({ repository: repo, discussionId });
Defensive patterns

Strategy: validation

Validate before calling

const isValidRepo = (repo) => typeof repo === 'string' && /^[^\/\s]+\/[^\/\s]+$/.test(repo.trim());
if (!isValidRepo(process.env.GITHUB_REPOSITORY)) throw new Error('Expected repository as owner/repo');

Type guard

const isOwnerRepo = (v) => typeof v === 'string' && /^[^\/\s]+\/[^\/\s]+$/.test(v);

Try / catch

try {
  const key = announcementKey({ repository, discussionId });
} catch (err) {
  if (err.message === 'invalid repository') {
    console.error(`repository must be 'owner/repo', got: ${JSON.stringify(repository)}`);
  }
  throw err;
}

Prevention

When it happens

Trigger: main() passes an input object whose repository field is undefined/null, an empty string, a bare repo name like 'ECC' without owner, a full URL like 'https://github.com/owner/repo', or a value containing whitespace or multiple slashes.

Common situations: Parsing the repo from GITHUB_REPOSITORY incorrectly; passing a GitHub URL instead of 'owner/repo'; forgetting to thread the repository through a config object so it arrives undefined.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16). Data as JSON: /api/errors/c22034f3008d23ea. Report an issue: GitHub.

Appendix: source

Thrown at scripts/discord/announcement-core.mjs:24

  return discussion?.category?.name === 'Announcements';
}

export function releaseMarker(tag) {
  const normalized = String(tag || '').trim();
  if (!normalized) throw new Error('release tag is required');
  return `<!-- ecc-release:${normalized} -->`;
}

export function findReleaseDiscussion(discussions, marker) {
  return discussions.find(item => (
    item?.category?.name === 'Announcements'
    && typeof item.body === 'string'
    && item.body.includes(marker)
  )) || null;
}

export function announcementKey({ repository, discussionId }) {
  if (!/^[^/\s]+\/[^/\s]+$/.test(String(repository || ''))) throw new Error('invalid repository');
  if (!/^[A-Za-z0-9_-]+$/.test(String(discussionId || ''))) throw new Error('invalid discussion id');
  return `${repository}:discussion:${discussionId}`;
}

export function buildDiscordPayload({ title, body, url, key }) {
  const discussionId = String(key).split(':').at(-1);
  const footer = `ecc:${discussionId}`;
  const description = String(body || '').trim().slice(0, DISCORD_DESCRIPTION_LIMIT);
  const nonce = `ecc-${createHash('sha256').update(String(key)).digest('hex').slice(0, 16)}`;
  return {
    allowed_mentions: { parse: [] },
    nonce,
    enforce_nonce: true,
    embeds: [{
      title: String(title || 'ECC announcement').trim().slice(0, 256),
      description,
      url: String(url || ''),
      footer: { text: footer },

View on GitHub (pinned to 8321021c54)