Tencent/WeKnora · error

marshal credentials: %w

Error message

marshal credentials: %w

What it means

parseYuqueConfig marshals the raw credentials map to JSON before unmarshalling into the typed Config struct. This error wraps any failure from json.Marshal(config.Credentials), which in practice is extremely rare for map/slice credential values. It indicates the stored credentials value is of a type that cannot be JSON-encoded.

Source

Thrown at internal/datasource/connector/yuque/types.go:71

	}
	if !strings.Contains(url, "://") {
		url = "https://" + url
	}
	url = strings.TrimRight(url, "/")
	return url
}

// parseYuqueConfig extracts and validates Yuque-specific configuration.
// Uses JSON marshal/unmarshal roundtrip (consistent with Feishu's parseFeishuConfig)
// rather than single-field type assertion, because we have multiple fields with
// optional defaults.
func parseYuqueConfig(config *types.DataSourceConfig) (*Config, error) {
	if config == nil {
		return nil, fmt.Errorf("%w: config is nil", datasource.ErrInvalidConfig)
	}
	credBytes, err := json.Marshal(config.Credentials)
	if err != nil {
		return nil, fmt.Errorf("marshal credentials: %w", err)
	}
	var cfg Config
	if err := json.Unmarshal(credBytes, &cfg); err != nil {
		return nil, fmt.Errorf("parse yuque credentials: %w", err)
	}
	if strings.TrimSpace(cfg.APIToken) == "" {
		return nil, fmt.Errorf("%w: api_token is required", datasource.ErrInvalidCredentials)
	}
	if err := datasource.ValidateConnectorBaseURL(cfg.GetBaseURL()); err != nil {
		return nil, err
	}
	return &cfg, nil
}

// --- Yuque API response types ---

// flexibleStatus accepts either a string ("1") or a number (1) for the doc
// `status` field. Yuque's OpenAPI spec declares `status` as string, but the

View on GitHub (pinned to 988cbb0330)

Solutions

  1. Inspect what type the credential store returns; ensure it is a JSON-encodable map or struct.
  2. Log the Go type of config.Credentials and fix the loader to decode into map[string]any.
  3. If wrapping a lower-level error, fix that underlying cause first — this line only re-wraps it.

Example fix

// before
creds := map[string]any{"api_token": make(chan int)}
// after
creds := map[string]any{"api_token": "your-token"}
Defensive patterns

Strategy: validation

Validate before calling

if _, err := json.Marshal(config.Credentials); err != nil {
    return fmt.Errorf("credentials not JSON-encodable: %w", err)
}

Type guard

func isJSONEncodable(v any) bool { _, err := json.Marshal(v); return err == nil }

Try / catch

if _, err := json.Marshal(config.Credentials); err != nil {
    log.Printf("unsupported credentials type %T", config.Credentials)
    return err
}

Prevention

When it happens

Trigger: config.Credentials contains a value json.Marshal cannot encode (e.g. a channel, func, or cyclic structure) rather than a normal map[string]interface{} of string credentials.

Common situations: Credentials were programmatically constructed with unsupported types instead of being decoded from JSON/YAML config; a custom credential store returned an exotic Go type.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


AI-assisted analysis of Tencent/WeKnora@988cbb0330 (2026-09-02). Data as JSON: /api/errors/c4f8614b7934841c. Report an issue: GitHub.