gastownhall/beads · error

ExternalDoltConfig: must set Socket or (Host, Port)

Error message

ExternalDoltConfig: must set Socket or (Host, Port)

What it means

A dependency's optional Metadata field, when non-empty, must be valid JSON. validatePublicCreateDependencies runs json.Valid on it and rejects the request with the dependency's index in the message, wrapped as ErrValidation.

Solutions

  1. Marshal with json.Marshal (or json.Marshal of a map/struct) instead of building the string by hand.
  2. Validate with json.Valid before submitting.
  3. Set Metadata to "" if no metadata is needed — empty string is allowed.

Example fix

// before
Metadata: `{"key: "value"}` // malformed
// after
b, _ := json.Marshal(map[string]string{"key": "value"})
Metadata: string(b)
Defensive patterns

Strategy: validation

Validate before calling

for i, d := range req.Dependencies {
    if d.Metadata != "" && !json.Valid([]byte(d.Metadata)) {
        return fmt.Errorf("dependency %d metadata must be valid JSON", i)
    }
}

Try / catch

if err := store.ExecuteCreate(ctx, req); err != nil {
    if errors.Is(err, storage.ErrValidation) && strings.Contains(err.Error(), "metadata must be valid JSON") { /* fix metadata */ }
    return err
}

Prevention

When it happens

Trigger: ExecuteCreate/ValidatePublicCreateRequest where request.Dependencies[index].Metadata is a non-empty string that fails json.Valid (e.g. bare text, single quotes, trailing comma); check at public_create.go:171.

Common situations: Hand-writing metadata strings, templating JSON with unescaped quotes, passing map-like text instead of serialized JSON, or copy-pasting metadata from logs with truncation.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/a68d1dea22348a2f. Report an issue: GitHub.

Appendix: source

Thrown at internal/configfile/external_dolt_config.go:48

}

func (c ExternalDoltConfig) ResolvedUser() string {
	if c.User == "" {
		return ExternalDoltConfigDefaultUser
	}
	return c.User
}

func (c ExternalDoltConfig) Validate() error {
	hasHost := c.Host != ""
	hasPort := c.Port != 0
	hasSocket := c.Socket != ""

	switch {
	case hasSocket && (hasHost || hasPort):
		return errors.New("ExternalDoltConfig: set either Socket OR (Host, Port), not both")
	case !hasSocket && !hasHost && !hasPort:
		return errors.New("ExternalDoltConfig: must set Socket or (Host, Port)")
	case hasHost && !hasPort:
		return errors.New("ExternalDoltConfig: Host requires Port")
	case !hasHost && hasPort:
		return errors.New("ExternalDoltConfig: Port requires Host")
	}

	if hasHost && (c.Port < 1 || c.Port > 65535) {
		return fmt.Errorf("ExternalDoltConfig: Port %d out of range [1, 65535]", c.Port)
	}

	if hasSocket && !filepath.IsAbs(c.Socket) {
		return fmt.Errorf("ExternalDoltConfig: Socket %q is not absolute", c.Socket)
	}

	switch {
	case c.TLSCert != "" && c.TLSKey == "":
		return errors.New("ExternalDoltConfig: TLSCert set without TLSKey")
	case c.TLSCert == "" && c.TLSKey != "":

View on GitHub (pinned to 71377f2769)