wavetermdev/waveterm · error
static files not available before app initialization; use Ap
Error message
static files not available before app initialization; use AppInit to access files during initialization
What it means
ReadStaticFile reads from the app's embedded static filesystem, which is attached to the default client only after app initialization completes. Calling it earlier (StaticFS is nil) returns this error directing you to AppInit, where static files are accessible during initialization.
Source
Thrown at tsunami/app/defaultclient.go:219
secretDesc = meta.Desc
secretOptional = meta.Optional
}
client.DeclareSecret(secretName, secretDesc, secretOptional)
return os.Getenv(secretName)
}
func PrintAppManifest() {
client := engine.GetDefaultClient()
client.PrintAppManifest()
}
// ReadStaticFile reads a file from the embedded static filesystem.
// The path MUST start with "static/" (e.g., "static/config.json").
// Returns the file contents or an error if the file doesn't exist or can't be read.
func ReadStaticFile(path string) ([]byte, error) {
client := engine.GetDefaultClient()
if client.StaticFS == nil {
return nil, errors.New("static files not available before app initialization; use AppInit to access files during initialization")
}
if !strings.HasPrefix(path, "static/") {
return nil, fmt.Errorf("ReadStaticFile path must start with 'static/': %w", fs.ErrNotExist)
}
// Strip "static/" prefix since the FS is already sub'd to the static directory
relativePath := strings.TrimPrefix(path, "static/")
return fs.ReadFile(client.StaticFS, relativePath)
}
// OpenStaticFile opens a file from the embedded static filesystem.
// The path MUST start with "static/" (e.g., "static/config.json").
// Returns an fs.File or an error if the file doesn't exist or can't be opened.
func OpenStaticFile(path string) (fs.File, error) {
client := engine.GetDefaultClient()
if client.StaticFS == nil {
return nil, errors.New("static files not available before app initialization; use AppInit to access files during initialization")
}
if !strings.HasPrefix(path, "static/") {View on GitHub (pinned to a4447c1563)
Solutions
- Move the ReadStaticFile call after app initialization completes (post-AppInit).
- If you need files during initialization, read them inside the AppInit callback where StaticFS is available.
- Ensure the app's startup path actually populates StaticFS before dependent code runs.
- For pure-asset needs, use embed.FS directly in your package instead of the app client.
- Add a startup ordering guard/assert that StaticFS is set before consumers run.
Example fix
// before
func init() {
data, _ := app.ReadStaticFile("static/config.json") // too early
}
// after
func OnInit(ctx context.Context) error {
data, err := app.ReadStaticFile("static/config.json") // inside AppInit
...
} Defensive patterns
Strategy: validation
Validate before calling
if client.StaticFS == nil {
return nil, fmt.Errorf("static FS not ready; call from AppInit or later")
} Try / catch
data, err := app.ReadStaticFile("static/config.json")
if err != nil {
return fmt.Errorf("read static config: %w", err)
} Prevention
- Call static-file helpers only after AppInit completes.
- Use the AppInit callback for init-time asset access.
- Never read static assets in package init()/constructors.
- Assert StaticFS != nil in startup ordering checks.
When it happens
Trigger: Calling tsunami/app.ReadStaticFile(path) before the app's initialization finished — engine.GetDefaultClient() returns a client whose StaticFS field is still nil (outside or early in AppInit).
Common situations: Reading static config assets at package init time; accessing embedded files in constructors that run before AppInit; tests that call ReadStaticFile without booting the app.
Related errors
- stream broker not available
- no route id available
- beginning of file
- procinfo: process not found
- integer overflow
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/c5597635a3b7883e.
Report an issue: GitHub.