kgretzky/evilginx2 · error

phishlet '%s' is a template - you have to 'create' child phi

Error message

phishlet '%s' is a template - you have to 'create' child phishlet from it, with predefined parameters, before you can enable it.

What it means

SetSiteEnabled throws this when the target phishlet is marked isTemplate. Template phishlets are blueprints; they cannot be enabled directly because they lack concrete parameters. Users must 'create' a child phishlet from the template with the required parameters, then enable the child.

Source

Thrown at core/config.go:404

			if c.PhishletConfig(l.Phishlet).Enabled {
				return true
			}
		}
	}
	return false
}

func (c *Config) SetSiteEnabled(site string) error {
	pl, err := c.GetPhishlet(site)
	if err != nil {
		log.Error("%v", err)
		return err
	}
	if c.PhishletConfig(site).Hostname == "" {
		return fmt.Errorf("enabling phishlet '%s' requires its hostname to be set up", site)
	}
	if pl.isTemplate {
		return fmt.Errorf("phishlet '%s' is a template - you have to 'create' child phishlet from it, with predefined parameters, before you can enable it.", site)
	}
	c.PhishletConfig(site).Enabled = true
	c.refreshActiveHostnames()
	c.VerifyPhishlets()
	log.Info("enabled phishlet '%s'", site)

	c.SavePhishlets()
	return nil
}

func (c *Config) SetSiteDisabled(site string) error {
	if _, err := c.GetPhishlet(site); err != nil {
		log.Error("%v", err)
		return err
	}
	c.PhishletConfig(site).Enabled = false
	c.refreshActiveHostnames()
	log.Info("disabled phishlet '%s'", site)

View on GitHub (pinned to 4c0988a1d9)

Solutions

  1. Create a child phishlet from the template: phishlets create <child> <template> <param>... , then enable the child
  2. Enable the child phishlet's name, not the template/parent name
  3. List phishlets to identify which entries are templates before enabling
  4. Update scripts/config to reference the created child phishlet name

Example fix

// console
// before
phishlets enable oauth-template
// after
phishlets create oauth-live oauth-template hostname oauth.example.com
phishlets enable oauth-live
Defensive patterns

Strategy: try-catch

Validate before calling

// before SetSiteEnabled, ensure the phishlet is not a template
pl, err := c.GetPhishlet(site)
if err != nil { return err }
if pl.IsTemplate() { return fmt.Errorf("%s is a template; create a child phishlet first", site) }
c.SetSiteEnabled(site, true)

Type guard

func isTemplatePhishlet(c *Config, site string) bool {
    pl, err := c.GetPhishlet(site)
    return err != nil || pl.IsTemplate()
}

Try / catch

if err := c.SetSiteEnabled(site, true); err != nil {
    if strings.Contains(err.Error(), "is a template") {
        log.Printf("create a child from %s with 'phishlets create <child> %s ...', then enable the child", site, site)
    }
    return err
}

Prevention

When it happens

Trigger: Running 'phishlets enable <template-name>' (handlePhishlets → SetSiteEnabled) on a phishlet loaded as a template, or on a parent phishlet instead of a child created from it.

Common situations: New users confusing template phishlets with enable-ready ones; enabling the parent name after creating a differently-named child; automation referencing the template name from a config file.

Related errors


AI-assisted analysis of kgretzky/evilginx2@4c0988a1d9 (2026-09-05). Data as JSON: /api/errors/5fcb5d0e14f59a5a. Report an issue: GitHub.