This is expected behavior. When you assign to an index of an element of an object, R will create the element if it doesn't exist. In your example "dimnames" doesn't exist in aa, so R tries to create "dimnames" based on what you're assigning to it. Consider assigning elements named "a", "b", and "c" of a list:
> L <- list()
> L$a[[1]] <- 5
> L$b[[3]] <- "foo"
> L$c[[4]] <- c(1,2,3)
> class(L$a)
[1] "numeric"
> class(L$b)
[1] "character"
> class(L$c)
[1] "list"
Now the problem with saying L$a[[1]] <- anything is that L$a doesn't exist yet. What happens when an element doesn't exist is that R just creates the simplest type of element that would work. As you can see, L$a[[1]] <- 5 would make sense if L$a is a numeric vector, so R makes it a numeric vector. L$b[[3]] <- "foo" doesn't make sense if L$b is a numeric vector, but it would make sense if L$b is a character vector, so that's what R creates. But L$c[[4]] <- c(1,2,3) can only happen if L$c is a list, so in that case you get a list.
In your case, it tries to create dimnames according to that rule; so it makes dimnames(aa) a list, but it only makes dimnames(bb) a character vector. But dimnames has an extra constraint that it has to be a list, so it objects and you get an error.