In lavaan version 0.6-20 and above, specifying a composite construct (using the <~ operator) that also has reflective indicators (using the =~ operator) crashes during model compilation with the following error:
Error in solve.default(wtw) : 'a' is 0-diml
This model compiles and fits successfully in lavaan 0.6-19 (where <~ was translated internally to regressions) but fails in newer versions due to the newly introduced native composite variable LISREL representation code.
Minimal Reproducible Example (MRE)
library(lavaan)
# Minimal syntax with both reflective and formative indicators
model <- '
# Reflective indicators
A =~ v3 + v4
# Formative/Composite indicators
A <~ v1 + v2
'
# This call crashes in 0.6-20 and 0.6-21
fit <- sem(model)
Analysis by Analysis by Google Antigravity and Gemini 3.5 Flash.
The crash occurs during the model-implied covariance matrix calculation:
Error in solve.default(wtw) : 'a' is 0-diml
Calls: sem ... lav_model_sigma -> lav_lisrel_sigma -> solve -> solve.default
Root Cause Analysis
The bug resides in the internal function lav_lisrel_sigma (in R/lav_model_sigma.R).
When a model utilizes composites (<~), lavaan populates the weight matrix WMAT in MLIST, directing the LISREL representation builder down the else branch of lav_lisrel_sigma:
cov.idx <- which(apply(LAMBDA, 1L, function(x) sum(x == 0) == ncol(LAMBDA)))
clv.idx <- which(apply(LAMBDA, 2L, function(x) sum(x == 0) == nrow(LAMBDA)))
rlv.idx <- seq_len(ncol(LAMBDA))[-clv.idx]
LW <- LAMBDA + WMAT
Tmat <- diag(nrow(LAMBDA))
Tmat[cov.idx, cov.idx] <- THETA[cov.idx, cov.idx]
wtw <- t(LW[, clv.idx, drop = FALSE]) %*% Tmat %*% LW[, clv.idx, drop = FALSE]
wtw.inv <- solve(wtw)
Analysis of the Bug:
-
clv.idx is populated by identifying the columns of LAMBDA that contain only zeroes (i.e. latent variables that have no reflective indicators).
- If all composite constructs in the model are identified by at least one reflective indicator (a very common scenario like the $2$-step MIMIC model structure where
A =~ v3 + v4 and A <~ v1 + v2), then LAMBDA has no columns that are entirely zero.
- Consequently,
clv.idx is empty (integer(0)).
- Because
clv.idx is empty, the matrix subset LW[, clv.idx, drop = FALSE] has zero columns, resulting in wtw being a $0 \times 0$ matrix.
- Calling
solve(wtw) on a $0 \times 0$ matrix triggers Error in solve.default(wtw) : 'a' is 0-diml.
Suggested Code Fix
In lav_lisrel_sigma (in R/lav_model_sigma.R), a guard check should be added to ensure that clv.idx is not empty before attempting to calculate and invert the weight matrix wtw:
# Proposed correction in R/lav_model_sigma.R
WTW.inv <- diag(ncol(LAMBDA))
if (length(clv.idx) > 0L) {
wtw <- t(LW[, clv.idx, drop = FALSE]) %*% Tmat %*% LW[, clv.idx, drop = FALSE]
wtw.inv <- solve(wtw)
WTW.inv[clv.idx, clv.idx] <- wtw.inv
}
This fix prevents attempting matrix operations on empty subsets and correctly falls back to treating the latent variables appropriately.
In
lavaanversion 0.6-20 and above, specifying a composite construct (using the<~operator) that also has reflective indicators (using the=~operator) crashes during model compilation with the following error:This model compiles and fits successfully in
lavaan 0.6-19(where<~was translated internally to regressions) but fails in newer versions due to the newly introduced native composite variable LISREL representation code.Minimal Reproducible Example (MRE)
Analysis by Analysis by Google Antigravity and Gemini 3.5 Flash.
The crash occurs during the model-implied covariance matrix calculation:
Root Cause Analysis
The bug resides in the internal function
lav_lisrel_sigma(inR/lav_model_sigma.R).When a model utilizes composites (
<~),lavaanpopulates the weight matrixWMATinMLIST, directing the LISREL representation builder down theelsebranch oflav_lisrel_sigma:Analysis of the Bug:
clv.idxis populated by identifying the columns ofLAMBDAthat contain only zeroes (i.e. latent variables that have no reflective indicators).A =~ v3 + v4andA <~ v1 + v2), thenLAMBDAhas no columns that are entirely zero.clv.idxis empty (integer(0)).clv.idxis empty, the matrix subsetLW[, clv.idx, drop = FALSE]has zero columns, resulting inwtwbeing asolve(wtw)on aError in solve.default(wtw) : 'a' is 0-diml.Suggested Code Fix
In
lav_lisrel_sigma(inR/lav_model_sigma.R), a guard check should be added to ensure thatclv.idxis not empty before attempting to calculate and invert the weight matrixwtw:This fix prevents attempting matrix operations on empty subsets and correctly falls back to treating the latent variables appropriately.