infiniflow/ragflow · error · Error

Space ID is required

Error message

Space ID is required

What it means

Thrown in web/src/pages/skills/hooks.ts:1005 by deleteSkill when the spaceId argument is falsy. Skill deletion needs the space id both to find the skill's folder and to clean up its search index entries, so an absent id is a caller-side error detected before any network activity. The catch wraps it into a generic 'skills.deleteError' toast.

Source

Thrown at web/src/pages/skills/hooks.ts:1005

        return false;
      } finally {
        setLoading(false);
      }
    },
    [t, fetchSkills, ensureSkillSpaceFolder],
  );

  // Delete a skill
  const deleteSkill = useCallback(
    async (
      skillId: string,
      _skillName?: string,
      spaceId?: string,
      spaceName?: string,
      folderId?: string,
    ): Promise<boolean> => {
      try {
        if (!spaceId) throw new Error('Space ID is required');
        if (!spaceName) throw new Error('Space name is required');
        const normalizedSpaceId = spaceId.trim();
        const normalizedSpaceName = spaceName.trim();

        let targetFolderId: string | null = folderId || null;

        // If folderId not provided, try to find the skill in current skills state
        if (!targetFolderId) {
          const skillInState = skills.find((s) => s.id === skillId);
          if (skillInState && (skillInState as any)._folderId) {
            targetFolderId = (skillInState as any)._folderId;
          }
        }

        // Fallback: search in file system if not found
        if (!targetFolderId) {
          const spaceFolderId = await ensureSkillSpaceFolder(
            normalizedSpaceName,

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Pass an options object ({skillId, spaceId, spaceName, folderId}) instead of positional args to prevent order bugs
  2. Disable the delete action in the UI until the active space is resolved
  3. Guard in the UI layer: if (!activeSpaceId) show a message instead of invoking deleteSkill
  4. Grep all deleteSkill call sites to confirm argument alignment after the signature change

Example fix

// before
const deleteSkill = useCallback(
  async (
    skillId: string,
    _skillName?: string,
    spaceId?: string,
    spaceName?: string,
    folderId?: string,
  ): Promise<boolean> => {
    if (!spaceId) throw new Error('Space ID is required');

// after
type DeleteSkillArgs = {
  skillId: string;
  spaceId: string;
  spaceName: string;
  folderId?: string;
};
const deleteSkill = useCallback(
  async ({ skillId, spaceId, spaceName, folderId }: DeleteSkillArgs) => {
    if (!spaceId.trim() || !spaceName.trim()) {
      message.error(t('skills.errors.spaceRequired'));
      return false;
    }
Defensive patterns

Strategy: validation

Validate before calling

const canDelete = (skillId?: string, spaceId?: string, spaceName?: string) =>
  [skillId, spaceId, spaceName].every((v) => typeof v === 'string' && v.trim().length > 0);

Type guard

const hasSpaceContext = (c: unknown): c is { spaceId: string; spaceName: string } =>
  typeof c === 'object' && c !== null &&
  typeof c.spaceId === 'string' && c.spaceId.length > 0 &&
  typeof c.spaceName === 'string' && c.spaceName.length > 0;

Prevention

When it happens

Trigger: Calling deleteSkill without the spaceId positional argument; the spaces context not yet loaded so the active space id is undefined; refactor changed the parameter order (skillId, _skillName, spaceId, spaceName, folderId) and a caller passed them in the old order.

Common situations: Delete clicked before the space selector finished loading. Signature drift after the _skillName parameter was inserted, leaving older call sites misaligned. Space id stored as empty string in route state.

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/6eabb9752555b627. Report an issue: GitHub.